Use Dataset created from 02_CLS_Data_Summary_2022_0914_Data_Analysis
File
Loading Data
Load Google Sheet
Final_CLS_2022_Study_List_Non_Search_model_file <- read_sheet(
"https://docs.google.com/spreadsheets/d/1N48rTeq7md0v8w8pG_8XIiuapPHQAeO5WoWIB3eaceI/edit#gid=1449351377",
sheet = "FinalDataset_2022_Update"
) %>%
mutate(
Significant_Spend =
as.numeric(
case_when(
probability_of_lift >= 0.9 ~ 1,
TRUE ~ 0
)
),
country = case_when(
country == "NA" ~ "US",
TRUE ~ country
),
region_v2 = case_when(
country == "US" ~ "NA",
country == "CA" ~ "NA",
country == "US + CA" ~ "NA",
TRUE ~ region
)
) %>%
filter(channel != "Search") %>%
# filter out studies without reported lifts
filter(exposed != -1) %>%
# filter out google pay study
filter(study_id != "149142217") %>%
# filter out very negative absolute lifts
filter(absolute_lift > -1000) %>%
mutate(
pa = case_when(
pa == "Google Ads" ~ "SMB", # Step 1
pa == "YouTube" & conversion != "Type 256522942 ([MCC] YouTube TV - Web - Trial Start)" ~ "YTMP", # Step 2
pa == "YouTube Premium" ~ "YTMP", # Step 2
conversion == "Type 256522942 ([MCC] YouTube TV - Web - Trial Start)" ~ "YouTube TV", # Step 2
pa == "Cloud" & conversion != "Type 14257803 (Enterprise - Apps - Signup Confirm - Unique)" ~ "Cloud Workspace", # Step 3
pa == "Cloud" & conversion == "Type 14257803 (Enterprise - Apps - Signup Confirm - Unique)" ~ "Cloud GCP", # Step 3
pa == "Project Fi" ~ "Google Fi", # Step 4
pa == "Google Chrome" ~ "Chrome",
TRUE ~ pa
)
) %>%
mutate(
parsed_type = parse_number(conversion),
grouped_conversion = case_when(
conversion %in% c("Chromebook Microsite Referral Clicks Q4 2015", "Type 251422729 (Chromebooks Microsite Referral Clicks (Q4 2017))") ~ "Chromebook Referrals",
conversion %in% c("Desktop Downloads", "Type 11541547 (Desktop Download)") ~
"Desktop Downloads",
pa == "Pixel" ~ "Mobile Conversions",
pa == "DSM" ~ "Non-Mobile Device Conversions",
conversion == "Type 302982954 (Lena - P Lead)" ~ "Lena P Lead",
conversion == "Type 288347008 (LENA - B Lead)" ~ "Lena B Lead",
conversion == "Type 288697653 (LENA - Q Lead)" ~ "Lena Q Lead",
parsed_type %in% c(181283993, 855508686) ~ "Workspace Free Trial Start",
parsed_type == 330755641 ~ "Microsite Conversions",
parsed_type == 14257803 ~ "Enterprise Signups",
parsed_type == 289680712 ~ "Google(iOs) First Open",
parsed_type == 256522942 ~ "YouTube TV - Web - Trial Start",
parsed_type %in% c(452391534, 221497833, 277150074) ~ "Trial Signups Complete",
TRUE ~ conversion
),
pa = case_when(
conversion == "Type 288697653 (LENA - Q Lead)" ~ "SMB-QLead",
TRUE ~ pa
)
) %>%
filter(absolute_lift > 0)
# all.equal(Final_CLS_2022_Study_List_Non_Search_model_file,Final_CLS_2022_Study_List_Non_Search_v3)
Create All Response Curves only normal powers
Folder for all Output and scripts
file.sources <- list.files(path = "RScripts/", pattern = "*.R", full.names = TRUE)
sapply(file.sources, source, .GlobalEnv)
RScripts/best_ind_function.R RScripts/export_rplots_function.R RScripts/export_rplots_function2.R
value ? ? ?
visible FALSE FALSE FALSE
RScripts/graphing_function.R RScripts/graphing_function_elasticnet.R RScripts/graphing_function_rlm.R
value ? ? ?
visible FALSE FALSE FALSE
RScripts/graphing_function2.R RScripts/graphing_function3.R RScripts/graphing_function4.R
value ? ? ?
visible FALSE FALSE FALSE
RScripts/graphing_function4_w_anom.R RScripts/model_wrapper_function.R RScripts/model_wrapper_function2.R
value ? ? ?
visible FALSE FALSE FALSE
RScripts/named_group_split.R RScripts/names_function.R RScripts/ridge_lasso_function.R RScripts/ridge_lasso_function2.R
value ? ? ? ?
visible FALSE FALSE FALSE FALSE
RScripts/ridge_lasso_function4.R RScripts/rlm_function.R RScripts/rlm_function2.R
value ? ? ?
visible FALSE FALSE FALSE
Check parameters
### powers to try
powers <- seq(0.1, 0.9, by = 0.01)
powers2 <- 1
### Powers to Try
#powers <- seq(0.1, 0.9, by = 0.01)
#powers2 <-seq(1.5,3, by = 0.25)
### Lambda parameters
parameters <- c(
# seq(0.1, 2, by =0.1) , seq(2, 5, 0.5) ,
seq(5, 29, 1)
,seq(30, 102, 4)
,seq(110, 1000, 15)
,seq(1000, 10020, 500)
)
### elasticnet parameters
alpha_parameters <- c(seq(0, 1, 0.25))
# For Testing Purposes
#alpha_parameters <- c(seq(1, 1, 1))
Testing Different Model Types
Chrome
Data Readin
start_time <- Sys.time()
Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre <-
Final_CLS_2022_Study_List_Non_Search_model_file %>%
filter(pa == "Chrome") %>%
mutate(
id2 = row_number()
)
df_test <-
Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre %>%
select(
region_v2, country, channel, tactic,
cost_spent_on_exposed_group:absolute_lift
)
iso_chrome <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1153)
iso_chrome$fit(df_test)
scores_train <- df_test %>%
iso_chrome$predict() %>%
arrange(desc(anomaly_score))
Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre2 <-
Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre %>%
left_join(scores_train, by = c("id2" = "id")) %>%
filter(average_depth > 3)
Final_CLS_2022_Study_List_Non_Search_model_file_chrome <-
Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre2 %>%
named_group_split(tactic)
Run Model
fits_non_search_chrome <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_chrome,poly_ind = 0)
best_ind_non_search_chrome <-
lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_chrome), best_ind_function,df = fits_non_search_chrome,
df2 = Final_CLS_2022_Study_List_Non_Search_model_file_chrome)
coef_non_search_chrome <- best_ind_non_search_chrome %>% bind_rows #make a matrix of all coefs
best_fit_non_search_chrome <- best_ind_non_search_chrome %>%
set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre, tactic))
Create Graph Object
graph_list_chrome <- lapply(1:length(best_fit_non_search_chrome), graphing_function4, df1 = best_fit_non_search_chrome, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_chrome)
end_time <- Sys.time()
time_chrome = end_time - start_time
time_chrome
Cloud
Data Readin
start_time <- Sys.time()
Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre <-
Final_CLS_2022_Study_List_Non_Search_model_file %>%
filter(pa %in% c("Cloud GCP", "Cloud Workspace")) %>%
mutate(
pa = "Cloud",
pa2 = "Cloud - All Channel"
) %>%
mutate(
id2 = row_number()
)
df_test <-
Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre %>%
# select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
select(
region_v2, country, channel, tactic,
# treatment_user_count:control,
cost_spent_on_exposed_group:absolute_lift, parsed_type
)
iso_cloud <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1153)
iso_cloud$fit(df_test)
scores_train <- df_test %>%
iso_cloud$predict() %>%
arrange(desc(anomaly_score))
Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre2 <-
Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre %>%
left_join(scores_train, by = c("id2" = "id"))
Final_CLS_2022_Study_List_Non_Search_model_file_cloud <-
Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre2 %>%
named_group_split(pa2)
Run Model
fits_non_search_cloud <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_cloud,poly_ind = 0)
best_ind_non_search_cloud <-
lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_cloud), best_ind_function,df = fits_non_search_cloud,
df2 = Final_CLS_2022_Study_List_Non_Search_model_file_cloud)
coef_non_search_cloud <- best_ind_non_search_cloud %>% bind_rows #make a matrix of all coefs
best_fit_non_search_cloud <- best_ind_non_search_cloud %>%
set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre, pa2))
Create Graph Object
graph_list_cloud <- lapply(1:length(best_fit_non_search_cloud), graphing_function4, df1 = best_fit_non_search_cloud, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_cloud)
end_time <- Sys.time()
time_cloud = end_time - start_time
YouTube
Data Readin
start_time <- Sys.time()
Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre <-
Final_CLS_2022_Study_List_Non_Search_model_file %>%
filter(pa %in% c("YouTube TV", "YTMP")) %>%
mutate(
pa = "YouTube",
pa2 = "YouTube"
) %>%
# filter(absolute_lift < 5000) %>%
mutate(
id2 = row_number()
)
df_test <-
Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre %>%
# select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
select(
region_v2, country, channel, tactic,
# treatment_user_count:control,
cost_spent_on_exposed_group:absolute_lift, parsed_type
)
iso_yt <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1153)
iso_yt$fit(df_test)
scores_train <- df_test %>%
iso_yt$predict() %>%
arrange(desc(anomaly_score))
Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre2 <-
Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre %>%
left_join(scores_train, by = c("id2" = "id")) %>%
filter(average_depth > 3.89)
Final_CLS_2022_Study_List_Non_Search_model_file_youtube <-
Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre2 %>%
named_group_split(region_v2)
Run Model
fits_non_search_youtube <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_youtube,poly_ind = 0)
best_ind_non_search_youtube <-
lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_youtube), best_ind_function,df = fits_non_search_youtube,
df2 = Final_CLS_2022_Study_List_Non_Search_model_file_youtube)
coef_non_search_youtube <- best_ind_non_search_youtube %>% bind_rows #make a matrix of all coefs
best_fit_non_search_youtube <- best_ind_non_search_youtube %>%
set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre, pa2))
Create Graph Object
graph_list_youtube <- lapply(1:length(best_fit_non_search_youtube), graphing_function4, df1 = best_fit_non_search_youtube, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_youtube)
end_time <- Sys.time()
time_youtube = end_time - start_time
DSM
Data Readin
start_time <- Sys.time()
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre <-
Final_CLS_2022_Study_List_Non_Search_model_file %>%
filter(pa == "DSM") %>%
filter(region_v2 != "APAC") %>%
# filter(absolute_lift < 1000) # %>%
# filter(study_id != '6297420') #%>%
# filter(study_id !='149161711') %>%
# filter(study_id != '148613002') %>%
# filter(study_id !='3284625') %>%
# filter(study_id !='3329131')
mutate(
id2 = row_number()
)
df_test <-
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre %>%
# select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
select(
region_v2, country, channel, tactic,
# treatment_user_count:control,
cost_spent_on_exposed_group:absolute_lift
)
iso_dsm <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)
iso_dsm$fit(df_test)
scores_train <- df_test %>%
iso_dsm$predict() %>%
arrange(desc(anomaly_score))
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre2 <-
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre %>%
left_join(scores_train, by = c("id2" = "id")) %>%
filter(average_depth > 5)
Final_CLS_2022_Study_List_Non_Search_model_file_dsm <-
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre2 %>%
named_group_split(region_v2, channel)
Run Model
fits_non_search_dsm <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_dsm,poly_ind = 0)
best_ind_non_search_dsm <-
lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_dsm), best_ind_function,df = fits_non_search_dsm,
df2 = Final_CLS_2022_Study_List_Non_Search_model_file_dsm)
coef_non_search_dsm <- best_ind_non_search_dsm %>% bind_rows #make a matrix of all coefs
best_fit_non_search_dsm <- best_ind_non_search_dsm %>%
set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre, region_v2,channel))
Create Graph Object
graph_list_dsm <- lapply(1:length(best_fit_non_search_dsm), graphing_function4, df1 = best_fit_non_search_dsm, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_dsm)
end_time <- Sys.time()
time_dsm = end_time - start_time
Pixel
Data Readin
start_time <- Sys.time()
Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre <-
Final_CLS_2022_Study_List_Non_Search_model_file %>%
filter(pa == "Pixel") %>%
mutate(
pa2 = "Pixel - All Channel"
) %>%
# filter(absolute_lift < 1000) %>%
# filter(study_id != '6297420') #%>%
# filter(study_id !='149161711') %>%
# filter(study_id != '148613002') %>%
# filter(study_id !='3284625') %>%
# filter(study_id !='3329131')
mutate(
id2 = row_number()
)
df_test <-
Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre %>%
# select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
select(
region_v2, country, channel, tactic,
# treatment_user_count:control,
cost_spent_on_exposed_group:absolute_lift
)
iso_pixel <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)
iso_pixel$fit(df_test)
scores_train <- df_test %>%
iso_pixel$predict() %>%
arrange(desc(anomaly_score))
Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre2 <-
Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre %>%
left_join(scores_train, by = c("id2" = "id")) %>%
filter(average_depth > 3.1)
Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre2
Final_CLS_2022_Study_List_Non_Search_model_file_pixel <-
Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre2 %>%
named_group_split(pa2)
Run Model
fits_non_search_pixel <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_pixel,poly_ind = 0)
best_ind_non_search_pixel <-
lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_pixel), best_ind_function,df = fits_non_search_pixel,
df2 = Final_CLS_2022_Study_List_Non_Search_model_file_pixel)
coef_non_search_pixel <- best_ind_non_search_pixel %>% bind_rows #make a matrix of all coefs
best_fit_non_search_pixel <- best_ind_non_search_pixel %>%
set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre, pa2))
Create Graph Object
graph_list_pixel <- lapply(1:length(best_fit_non_search_pixel), graphing_function4, df1 = best_fit_non_search_pixel, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_pixel)
end_time <- Sys.time()
time_pixel = end_time - start_time
Fi
Data Readin
start_time <- Sys.time()
Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre <-
Final_CLS_2022_Study_List_Non_Search_model_file %>%
filter(pa == "Google Fi") %>%
mutate(
pa2 = "Fi - All Channel"
) %>%
# filter(absolute_lift < 1000) %>%
# filter(study_id != '6297420') #%>%
# filter(study_id !='149161711') %>%
# filter(study_id != '148613002') %>%
# filter(study_id !='3284625') %>%
# filter(study_id !='3329131')
mutate(
id2 = row_number()
)
df_test <-
Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre %>%
# select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
select(
region_v2, country, channel, tactic,
# treatment_user_count:control,
cost_spent_on_exposed_group:absolute_lift
)
iso_fi <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)
iso_fi$fit(df_test)
scores_train <- df_test %>%
iso_fi$predict() %>%
arrange(desc(anomaly_score))
Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre2 <-
Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre %>%
left_join(scores_train, by = c("id2" = "id")) %>%
filter(average_depth > 4.75)
Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre2
Final_CLS_2022_Study_List_Non_Search_model_file_fi <-
Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre2 %>%
named_group_split(channel)
Run Model
fits_non_search_fi <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_fi,poly_ind = 0)
best_ind_non_search_fi <-
lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_fi), best_ind_function,df = fits_non_search_fi,
df2 = Final_CLS_2022_Study_List_Non_Search_model_file_fi)
coef_non_search_fi <- best_ind_non_search_fi %>% bind_rows #make a matrix of all coefs
best_fit_non_search_fi <- best_ind_non_search_fi %>%
set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre, pa2))
Create Graph Object
graph_list_fi <- lapply(1:length(best_fit_non_search_fi), graphing_function4, df1 = best_fit_non_search_fi, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_fi)
end_time <- Sys.time()
time_fi = end_time - start_time
SMB - QLeads
Data Readin
start_time <- Sys.time()
Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre <-
Final_CLS_2022_Study_List_Non_Search_model_file %>%
filter(grouped_conversion == 'Lena Q Lead') %>%
mutate(
pa2 = "SMB - Q-Lead"
) %>%
# filter(absolute_lift < 1000) %>%
# filter(study_id != '6297420') #%>%
# filter(study_id !='149161711') %>%
# filter(study_id != '148613002') %>%
# filter(study_id !='3284625') %>%
# filter(study_id !='3329131')
mutate(
id2 = row_number()
)
df_test <-
Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre %>%
# select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
select(
region_v2, country, channel, tactic,
# treatment_user_count:control,
cost_spent_on_exposed_group:absolute_lift
)
iso_smbq <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)
iso_smbq$fit(df_test)
scores_train <- df_test %>%
iso_smbq$predict() %>%
arrange(desc(anomaly_score))
Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre2 <-
Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre %>%
left_join(scores_train, by = c("id2" = "id")) %>%
filter(average_depth > 1)
Final_CLS_2022_Study_List_Non_Search_model_file_smbq <-
Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre2 %>%
named_group_split(pa2)
Run Model
fits_non_search_smbq <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_smbq,poly_ind = 0)
best_ind_non_search_smbq <-
lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_smbq), best_ind_function,df = fits_non_search_smbq,
df2 = Final_CLS_2022_Study_List_Non_Search_model_file_smbq)
coef_non_search_smbq <- best_ind_non_search_smbq %>% bind_rows #make a matrix of all coefs
best_fit_non_search_smbq <- best_ind_non_search_smbq %>%
set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre, pa2))
Create Graph Object
graph_list_smbq <- lapply(1:length(best_fit_non_search_smbq), graphing_function4, df1 = best_fit_non_search_smbq, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_smbq)
end_time <- Sys.time()
time_smbq = end_time - start_time
SMB - BLeads
Data Readin
start_time <- Sys.time()
Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre <-
Final_CLS_2022_Study_List_Non_Search_model_file %>%
filter(pa == "SMB" & grouped_conversion == 'Lena B Lead') %>%
mutate(
pa2 = "SMB - B-Lead"
) %>%
# filter(absolute_lift < 1000) %>%
# filter(study_id != '6297420') #%>%
# filter(study_id !='149161711') %>%
# filter(study_id != '148613002') %>%
# filter(study_id !='3284625') %>%
# filter(study_id !='3329131')
mutate(
id2 = row_number()
)
df_test <-
Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre %>%
# select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
select(
region_v2, country, channel, tactic,
# treatment_user_count:control,
cost_spent_on_exposed_group:absolute_lift
)
iso_smbb <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)
iso_smbb$fit(df_test)
scores_train <- df_test %>%
iso_smbb$predict() %>%
arrange(desc(anomaly_score))
Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre2 <-
Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre %>%
left_join(scores_train, by = c("id2" = "id")) %>%
filter(average_depth > 4)
Final_CLS_2022_Study_List_Non_Search_model_file_smbb <-
Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre2 %>%
named_group_split(channel)
Run Model
fits_non_search_smbb <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_smbb,poly_ind = 0)
best_ind_non_search_smbb <-
lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_smbb), best_ind_function,df = fits_non_search_smbb,
df2 = Final_CLS_2022_Study_List_Non_Search_model_file_smbb)
coef_non_search_smbb <- best_ind_non_search_smbb %>% bind_rows #make a matrix of all coefs
best_fit_non_search_smbb <- best_ind_non_search_smbb %>%
set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre, channel))
Create Graph Object
graph_list_smbb <- lapply(1:length(best_fit_non_search_smbb), graphing_function4, df1 = best_fit_non_search_smbb, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_smbb)
end_time <- Sys.time()
time_smbb = end_time - start_time
Export all graph lists
graph_names <- mget(ls(pat = 'graph_list_'))
df_names <- mget(setdiff(ls(pattern = 'Final_CLS_2022_Study_List_Non_Search_model_file_'), ls(pattern = "pre")))
#rm(Final_CLS_2022_Study_List_Non_Search_model_file_Chrome,Final_CLS_2022_Study_List_Non_Search_model_file_Cloud,Final_CLS_2022_Study_List_Non_Search_model_file_YouTube)
#lapply(1:length(graph_names),
# function(j) {
#lapply(1:length(df_names[[j]]),export_rplots_function2,starting_name = "Non_Search_",folder_name = folder_name,df_list = #df_names[[j]],graphing_list = graph_names[j][[1]])
# }
# )
Graphs with Anomaly Scores
graph_list.fi <- lapply(1:length(best_fit_non_search_fi), graphing_function4_w_anom, df1 = best_fit_non_search_fi, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_fi)
### Add GG Text Repel
ggplotly(graph_list.fi[[3]])
Create all Response Curves - Ridge/Lasso
start_time <- Sys.time()
fits.non.search.RIDGE_LASSO <- lapply(
1:length(df_names),
function(i) {
model_wrapper_function(df = df_names[i][[1]],poly_ind = 0)
}
)
Create all Response Curves - RLM
start_time <- Sys.time()
fits.non.search.RLM <- lapply(
1:length(df_names),
function(i) {
model_wrapper_function2(df = df_names[i][[1]])
}
)
end_time <- Sys.time()
combined_rlm_time <- start_time - end_time
best.ind.non.search.RLM <- lapply(
1:length(df_names),
function(i) {
lapply(1:length(df_names[i][[1]]), best_ind_function,df = fits.non.search.RLM[i][[1]],
df2 = df_names[i][[1]])
}
)
coef.non.search.RLM <- lapply(
1:length(df_names),
function (i){
best.ind.non.search.RLM[i][[1]] %>% bind_rows
}
) %>%
bind_rows() %>%
as.data.frame() %>%
mutate(
cost_p2 = 0,
lambda = 0,
alpha = 0,
powers2 = 0
) %>%
select(one_of(colnames(coef.2_matrix)))
best.fit.non.search.RLM <- lapply(1:length(df_names),
function(j) {
lapply(1:length(best.ind.non.search.RLM[[j]]),
function(i){
best.ind.non.search.RLM[j][[1]][i] %>%
set_names(nm = best.ind.non.search.RLM[j][[1]][[i]]["model"])
}
)
}
)
-combined_ridge_time+combined_rlm_time
Time difference of 32.768 mins
graph.list.rlm <- lapply(1:length(df_names),
function(i){
lapply(1:length(best.fit.non.search.RLM[i][[1]]), graphing_function_rlm, df1= best.fit.non.search.RLM[i],df2 = df_names[i])
}
)
graph.list.RIDGE_LASSO <- lapply(1:length(df_names),
function(i){
lapply(1:length(best.fit.non.search.RIDGE_LASSO[i][[1]]), graphing_function_elasticnet, df1= best.fit.non.search.RIDGE_LASSO[i],df2 = df_names[i])
}
)
Export all Plots
folder_name1 <- paste0("Output/", "outputfiles_", Sys.Date(), "_", "RLM", "/")
dir.create(folder_name1) # it will throw a warning if folder exists
Warning in dir.create(folder_name1) :
'Output\outputfiles_2022-11-08_RLM' already exists
lapply(1:length(df_names),
function(j) {
lapply(1:length(df_names[[j]]),export_rplots_function2,starting_name = "Non_Search_",folder_name = folder_name1,df_list = df_names[[j]],graphing_list = graph.list.rlm[j][[1]])
}
)
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
[[1]]
[[1]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Chrome_All_Channel.png"
[[1]][[2]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Chrome_non-REMK.png"
[[1]][[3]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Chrome_REMK.png"
[[2]]
[[2]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Cloud_Cloud_-_All_Channel.png"
[[3]]
[[3]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_EMEA__DISCOVERY.png"
[[3]][[2]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_EMEA__DISPLAY.png"
[[3]][[3]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_EMEA__YOUTUBE.png"
[[3]][[4]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_NA__DISCOVERY.png"
[[3]][[5]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_NA__DISPLAY.png"
[[3]][[6]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_NA__YOUTUBE.png"
[[4]]
[[4]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Google_Fi_DISCOVERY.png"
[[4]][[2]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Google_Fi_DISPLAY.png"
[[4]][[3]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Google_Fi_YOUTUBE.png"
[[5]]
[[5]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Pixel_Pixel_-_All_Channel.png"
[[6]]
[[6]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_SMB_DISCOVERY.png"
[[6]][[2]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_SMB_DISPLAY.png"
[[6]][[3]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_SMB_YOUTUBE.png"
[[7]]
[[7]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_SMB-QLead_SMB_-_Q-Lead.png"
[[8]]
[[8]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_YouTube_APAC.png"
[[8]][[2]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_YouTube_EMEA.png"
[[8]][[3]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_YouTube_NA.png"

folder_name2 <- paste0("Output/", "outputfiles_", Sys.Date(), "_", "ElasticNet", "/")
dir.create(folder_name2) # it will throw a warning if folder exists
Warning in dir.create(folder_name2) :
'Output\outputfiles_2022-11-08_ElasticNet' already exists
lapply(1:length(df_names),
function(j) {
lapply(1:length(df_names[[j]]),export_rplots_function2,starting_name = "Non_Search_",folder_name = folder_name2,df_list = df_names[[j]],graphing_list = graph.list.RIDGE_LASSO[j][[1]])
}
)
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
[[1]]
[[1]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Chrome_All_Channel.png"
[[1]][[2]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Chrome_non-REMK.png"
[[1]][[3]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Chrome_REMK.png"
[[2]]
[[2]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Cloud_Cloud_-_All_Channel.png"
[[3]]
[[3]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_EMEA__DISCOVERY.png"
[[3]][[2]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_EMEA__DISPLAY.png"
[[3]][[3]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_EMEA__YOUTUBE.png"
[[3]][[4]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_NA__DISCOVERY.png"
[[3]][[5]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_NA__DISPLAY.png"
[[3]][[6]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_NA__YOUTUBE.png"
[[4]]
[[4]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Google_Fi_DISCOVERY.png"
[[4]][[2]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Google_Fi_DISPLAY.png"
[[4]][[3]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Google_Fi_YOUTUBE.png"
[[5]]
[[5]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Pixel_Pixel_-_All_Channel.png"
[[6]]
[[6]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_SMB_DISCOVERY.png"
[[6]][[2]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_SMB_DISPLAY.png"
[[6]][[3]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_SMB_YOUTUBE.png"
[[7]]
[[7]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_SMB-QLead_SMB_-_Q-Lead.png"
[[8]]
[[8]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_YouTube_APAC.png"
[[8]][[2]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_YouTube_EMEA.png"
[[8]][[3]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_YouTube_NA.png"
Show Graphs
lapply(1:length(df_names),
function(j){
subplot(graph.list.rlm[j][[1]], nrows = length(graph.list.rlm[j][[1]]))
}
)
[[1]]
[[2]]
[[3]]
[[4]]
[[5]]
[[6]]
[[7]]
[[8]]
lapply(1:length(df_names),
function(i){
#p1 = graph_names[i][[1]]
do.call(grid.arrange,graph.list.rlm[i][[1]])
#return(grid.arrange(grobs = p1))
}
)
[[1]]
TableGrob (3 x 1) "arrange": 3 grobs
[[2]]
TableGrob (1 x 1) "arrange": 1 grobs
[[3]]
TableGrob (3 x 2) "arrange": 6 grobs
[[4]]
TableGrob (3 x 1) "arrange": 3 grobs
[[5]]
TableGrob (1 x 1) "arrange": 1 grobs
[[6]]
TableGrob (3 x 1) "arrange": 3 grobs
[[7]]
TableGrob (1 x 1) "arrange": 1 grobs
[[8]]
TableGrob (3 x 1) "arrange": 3 grobs
NA








lapply(1:length(df_names),
function(j){
subplot(graph.list.RIDGE_LASSO[j][[1]], nrows = length(graph.list.RIDGE_LASSO[j][[1]]))
}
)
[[1]]
[[2]]
[[3]]
[[4]]
[[5]]
[[6]]
[[7]]
[[8]]
lapply(1:length(df_names),
function(i){
#p1 = graph_names[i][[1]]
do.call(grid.arrange,graph.list.RIDGE_LASSO[i][[1]])
#return(grid.arrange(grobs = p1))
}
)
[[1]]
TableGrob (3 x 1) "arrange": 3 grobs
[[2]]
TableGrob (1 x 1) "arrange": 1 grobs
[[3]]
TableGrob (3 x 2) "arrange": 6 grobs
[[4]]
TableGrob (3 x 1) "arrange": 3 grobs
[[5]]
TableGrob (1 x 1) "arrange": 1 grobs
[[6]]
TableGrob (3 x 1) "arrange": 3 grobs
[[7]]
TableGrob (1 x 1) "arrange": 1 grobs
[[8]]
TableGrob (3 x 1) "arrange": 3 grobs
NA








Testing Metafor Package
Installing package into ‘C:/Users/Admin/Documents/R/win-library/4.1’
(as ‘lib’ is unspecified)
Warning: package ‘lmer4’ is not available for this version of R
A version of this package for your version of R might be available elsewhere,
see the ideas at
https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
Warning: unable to access index for repository http://www.stats.ox.ac.uk/pub/RWin/bin/windows/contrib/4.1:
cannot open URL 'http://www.stats.ox.ac.uk/pub/RWin/bin/windows/contrib/4.1/PACKAGES'
Warning in p_install(package, character.only = TRUE, ...) :
Warning in library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE, :
there is no package called ‘lmer4’
Warning in p_load(lmer4) : Failed to install/load:
lmer4
Installing package into ‘C:/Users/Admin/Documents/R/win-library/4.1’
(as ‘lib’ is unspecified)
also installing the dependencies ‘metadat’, ‘mathjaxr’, ‘metafor’
Warning: unable to access index for repository http://www.stats.ox.ac.uk/pub/RWin/bin/windows/contrib/4.1:
cannot open URL 'http://www.stats.ox.ac.uk/pub/RWin/bin/windows/contrib/4.1/PACKAGES'
There is a binary version available but the source version is later:
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/mathjaxr_1.6-0.zip'
Content type 'application/zip' length 970577 bytes (947 KB)
downloaded 947 KB
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/metafor_3.8-1.zip'
Content type 'application/zip' length 4483503 bytes (4.3 MB)
downloaded 4.3 MB
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/metaforest_0.1.3.zip'
Content type 'application/zip' length 217909 bytes (212 KB)
downloaded 212 KB
package ‘mathjaxr’ successfully unpacked and MD5 sums checked
package ‘metafor’ successfully unpacked and MD5 sums checked
package ‘metaforest’ successfully unpacked and MD5 sums checked
The downloaded binary packages are in
C:\Users\Admin\AppData\Local\Temp\RtmpGGjNkA\downloaded_packages
installing the source package ‘metadat’
trying URL 'https://cran.rstudio.com/src/contrib/metadat_1.2-0.tar.gz'
Content type 'application/x-gzip' length 964808 bytes (942 KB)
downloaded 942 KB
* installing *source* package 'metadat' ...
** package 'metadat' successfully unpacked and MD5 sums checked
** using staged installation
** R
** data
*** moving datasets to lazyload DB
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
converting help for package 'metadat'
finding HTML links ... done
dat.aloe2013 html
dat.anand1999 html
dat.assink2016 html
dat.axfors2021 html
dat.bakdash2021 html
dat.baker2009 html
dat.bangertdrowns2004 html
dat.baskerville2012 html
dat.bcg html
dat.begg1989 html
dat.berkey1998 html
dat.besson2016 html
dat.bonett2010 html
dat.bornmann2007 html
dat.bourassa1996 html
dat.cannon2006 html
dat.cohen1981 html
dat.colditz1994 html
dat.collins1985a html
dat.collins1985b html
dat.craft2003 html
dat.crede2010 html
dat.curtis1998 html
dat.dagostino1998 html
dat.damico2009 html
dat.debruin2009 html
dat.dogliotti2014 html
dat.dong2013 html
dat.dorn2007 html
dat.egger2001 html
dat.fine1993 html
dat.franchini2012 html
dat.frank2008 html
dat.gibson2002 html
dat.graves2010 html
dat.gurusamy2011 html
dat.hackshaw1998 html
dat.hahn2001 html
dat.hannum2020 html
dat.hart1999 html
dat.hartmannboyce2018 html
dat.hasselblad1998 html
dat.hine1989 html
dat.ishak2007 html
dat.kalaian1996 html
dat.kearon1998 html
dat.knapp2017 html
dat.konstantopoulos2011 html
dat.landenberger2005 html
dat.laopaiboon2015 html
dat.lau1992 html
dat.lee2004 html
dat.lehmann2018 html
dat.li2007 html
dat.lim2014 html
dat.linde2005 html
dat.linde2015 html
dat.linde2016 html
dat.lopez2019 html
dat.maire2019 html
dat.mccurdy2020 html
dat.mcdaniel1994 html
dat.michael2013 html
dat.molloy2014 html
dat.moura2021 html
dat.nakagawa2007 html
dat.nielweise2007 html
dat.nielweise2008 html
dat.normand1999 html
dat.obrien2003 html
dat.pagliaro1992 html
dat.pignon2000 html
dat.pritz1997 html
dat.raudenbush1985 html
dat.riley2003 html
dat.senn2013 html
dat.stowe2010 html
dat.tannersmith2016 html
dat.vanhowe1999 html
dat.viechtbauer2021 html
dat.white2020 html
dat.woods2010 html
dat.yusuf1985 html
datsearch html
metadat-package html
prep_dat html
** building package indices
** testing if installed package can be loaded from temporary location
*** arch - i386
*** arch - x64
** testing if installed package can be loaded from final location
*** arch - i386
*** arch - x64
** testing if installed package keeps a record of temporary installation path
* DONE (metadat)
The downloaded source packages are in
‘C:\Users\Admin\AppData\Local\Temp\RtmpGGjNkA\downloaded_packages’
metaforest installed
Warning: package ‘metaforest’ was built under R version 4.1.3
Warning: package ‘metafor’ was built under R version 4.1.3
Testing on DSM Data
Load in Data
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre <-
Final_CLS_2022_Study_List_Non_Search_model_file %>%
filter(pa == "DSM") %>%
filter(region_v2 != "APAC") %>%
# filter(absolute_lift < 1000) # %>%
# filter(study_id != '6297420') #%>%
# filter(study_id !='149161711') %>%
# filter(study_id != '148613002') %>%
# filter(study_id !='3284625') %>%
# filter(study_id !='3329131')
mutate(
id2 = row_number()
)
df_test <-
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre %>%
# select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
select(
region_v2, country, channel, tactic,
# treatment_user_count:control,
cost_spent_on_exposed_group:absolute_lift
)
iso_dsm <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)
iso_dsm$fit(df_test)
scores_train <- df_test %>%
iso_dsm$predict() %>%
arrange(desc(anomaly_score))
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4_V1 <-
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre %>%
left_join(scores_train, by = c("id2" = "id")) %>%
filter(average_depth > 5.1)
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4 <-
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4_V1 %>%
named_group_split(region_v2)
Standardize Data
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4_V1 %>%
mutate(
)
Run a Fixed-Effects Model
Documentation
#df_smd
i = 1
yi_DSM = Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]]['absolute_lift'] %>% unlist()
vi_DSM = Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]]['Significant_Spend']^1 %>% unlist()
split2 = factor(Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]]['channel'] %>% unlist(),labels = unique(Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]]['channel']) %>% unlist())
m_reg <- rma(yi = yi_DSM, # The d-column of the df, which contains Cohen's d
vi = vi_DSM # The vi-column of the df, which contains the variances
,mods = ~split2-1 #to remove intercept between slopes
)
Warning: There are outcomes with non-positive sampling variances.
Warning: Cannot compute QE-test, I^2, or H^2 when there are non-positive sampling variances in the data.
Mixed-Effects Model (k = 26; tau^2 estimator: REML)
tau^2 (estimated amount of residual heterogeneity): 14491.7080 (SE = 25164.4568)
tau (square root of estimated tau^2 value): 120.3815
I^2 (residual heterogeneity / unaccounted variability): 16.12%
H^2 (unaccounted variability / sampling variability): 1.19
R^2 (amount of heterogeneity accounted for): 87.03%
Test for Residual Heterogeneity:
QE(df = 23) = 32.2909, p-val = 0.0942
Test of Moderators (coefficients 2:3):
QM(df = 2) = 25.4474, p-val < .0001
Model Results:
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#rm(Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4_V1)#,mod1_test, i)
predict(mod1_test)
forest(mod1_test, slab = Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]]['study_name'] %>% unlist(), addcred = TRUE)

Additional Test
# Specify basic plot, mapping sex to the x-axis, effect size 'd' to the y-axis,
# and 'weights' to the weight parameter.
Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]] %>%
ggplot()+
aes(
x = cost_spent_on_exposed_group,
y = absolute_lift,
size = 1/sqrt(cost_spent_on_exposed_group)
) +
geom_point(shape = 1) + # Add scatter
geom_abline(intercept = m_reg$b[1], slope = m_reg$b[3]) + # Add regression line
theme_bw() + # Apply black and white theme
theme(legend.position = "none") # Remove legend
LS0tDQp0aXRsZTogIjAzX0NMU19TcGVuZF9SZXNwb25zZV9DdXJ2ZXNfTm9fUG9seSINCmF1dGhvcjogIkVzc2VuY2UgR2xvYmFsIEFkdmFuY2VkIEFuYWx5dGljcyBUZWFtIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vDQogICAgdGhlbWU6IGNlcnVsZWFuDQogICAgaGlnaGxpZ2h0OiB6ZW5idXJuDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpvcHRpb25zKGtuaXRyLnRhYmxlLmZvcm1hdCA9ICJodG1sIikNCm9wdGlvbnMoZGlnaXRzID0gNSkNCm9wdGlvbnMoc2NpcGVuID0gMTAwKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHRpZHkub3B0cyA9IGxpc3Qod2lkdGguY3V0b2ZmID0gODApLCB0aWR5ID0gVFJVRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcud2lkdGggPSAxNSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcuaGVpZ2h0ID0gMTApDQojIGluc3RhbGwucGFja2FnZXMoInBhY21hbiIpDQpsaWJyYXJ5KHBhY21hbikgIyBmb3IgcXVpY2sgbG9hZC9pbnN0YWxsIG9mIHBhY2thZ2VzDQpwX2xvYWQoZHBseXIsIHJlYWRyLCB0aWR5dmVyc2UsIHJldGljdWxhdGUsIGx1YnJpZGF0ZSwgamFuaXRvciwgc3FsZGYsIGdvb2dsZXNoZWV0czQpDQpwX2xvYWQoc2tpbXIsIHNwbGl0c3RhY2tzaGFwZSwgc3RyaW5nciwgcnFkYXRhdGFibGUpDQpwX2xvYWQobW9tZW50cykNCnBfbG9hZChrYWJsZUV4dHJhKQ0KcF9sb2FkKGdncGxvdDIsIHBsb3RseSwgZWNoYXJ0czRyLCBnZ3B1YnIsIGZvcmNhdHMsIHNjYWxlcywgUkNvbG9yQnJld2VyLGdyaWRFeHRyYSkNCnBfbG9hZChnZ3RoZW1lcykNCnBfbG9hZChjYXJldCwgcmVjaXBlcykNCnBfbG9hZChnbG1uZXQpDQpwX2xvYWQoZWxhc3RpY25ldCkNCnBfbG9hZChNZXRyaWNzKQ0KcF9sb2FkKGZhc3REdW1taWVzKQ0KcF9sb2FkKGJyb29tKQ0KcF9sb2FkKGh0bWx3aWRnZXRzKQ0KcF9sb2FkKHNvbGl0dWRlKQ0KcF9sb2FkKG1sYmVuY2gpDQpwX2xvYWQodXdvdCkNCmBgYA0KDQojIFVzZSBEYXRhc2V0IGNyZWF0ZWQgZnJvbSAwMl9DTFNfRGF0YV9TdW1tYXJ5XzIwMjJfMDkxNF9EYXRhX0FuYWx5c2lzIEZpbGUNCg0KIyMgTG9hZGluZyBEYXRhDQoNCiMjIyBMb2FkIEdvb2dsZSBTaGVldA0KDQpgYGB7cn0NCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlIDwtIHJlYWRfc2hlZXQoDQogICJodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9zcHJlYWRzaGVldHMvZC8xTjQ4clRlcTdtZDB2OHc4cEdfOFhJaXVhcFBIUUFlTzVXb1dJQjNlYWNlSS9lZGl0I2dpZD0xNDQ5MzUxMzc3IiwNCiAgc2hlZXQgPSAiRmluYWxEYXRhc2V0XzIwMjJfVXBkYXRlIg0KKSAlPiUNCiAgbXV0YXRlKA0KICAgIFNpZ25pZmljYW50X1NwZW5kID0NCiAgICAgIGFzLm51bWVyaWMoDQogICAgICAgIGNhc2Vfd2hlbigNCiAgICAgICAgICBwcm9iYWJpbGl0eV9vZl9saWZ0ID49IDAuOSB+IDEsDQogICAgICAgICAgVFJVRSB+IDANCiAgICAgICAgKQ0KICAgICAgKSwNCiAgICBjb3VudHJ5ID0gY2FzZV93aGVuKA0KICAgICAgY291bnRyeSA9PSAiTkEiIH4gIlVTIiwNCiAgICAgIFRSVUUgfiBjb3VudHJ5DQogICAgKSwNCiAgICByZWdpb25fdjIgPSBjYXNlX3doZW4oDQogICAgICBjb3VudHJ5ID09ICJVUyIgfiAiTkEiLA0KICAgICAgY291bnRyeSA9PSAiQ0EiIH4gIk5BIiwNCiAgICAgIGNvdW50cnkgPT0gIlVTICsgQ0EiIH4gIk5BIiwNCiAgICAgIFRSVUUgfiByZWdpb24NCiAgICApDQogICkgJT4lDQogIGZpbHRlcihjaGFubmVsICE9ICJTZWFyY2giKSAlPiUNCiAgIyBmaWx0ZXIgb3V0IHN0dWRpZXMgd2l0aG91dCByZXBvcnRlZCBsaWZ0cw0KICBmaWx0ZXIoZXhwb3NlZCAhPSAtMSkgJT4lDQogICMgZmlsdGVyIG91dCBnb29nbGUgcGF5IHN0dWR5DQogIGZpbHRlcihzdHVkeV9pZCAhPSAiMTQ5MTQyMjE3IikgJT4lDQogICMgZmlsdGVyIG91dCB2ZXJ5IG5lZ2F0aXZlIGFic29sdXRlIGxpZnRzDQogIGZpbHRlcihhYnNvbHV0ZV9saWZ0ID4gLTEwMDApICU+JQ0KICBtdXRhdGUoDQogICAgcGEgPSBjYXNlX3doZW4oDQogICAgICBwYSA9PSAiR29vZ2xlIEFkcyIgfiAiU01CIiwgIyBTdGVwIDENCiAgICAgIHBhID09ICJZb3VUdWJlIiAmIGNvbnZlcnNpb24gIT0gIlR5cGUgMjU2NTIyOTQyIChbTUNDXSBZb3VUdWJlIFRWIC0gV2ViIC0gVHJpYWwgU3RhcnQpIiB+ICJZVE1QIiwgIyBTdGVwIDINCiAgICAgIHBhID09ICJZb3VUdWJlIFByZW1pdW0iIH4gIllUTVAiLCAjIFN0ZXAgMg0KICAgICAgY29udmVyc2lvbiA9PSAiVHlwZSAyNTY1MjI5NDIgKFtNQ0NdIFlvdVR1YmUgVFYgLSBXZWIgLSBUcmlhbCBTdGFydCkiIH4gIllvdVR1YmUgVFYiLCAjIFN0ZXAgMg0KICAgICAgcGEgPT0gIkNsb3VkIiAmIGNvbnZlcnNpb24gIT0gIlR5cGUgMTQyNTc4MDMgKEVudGVycHJpc2UgLSBBcHBzIC0gU2lnbnVwIENvbmZpcm0gLSBVbmlxdWUpIiB+ICJDbG91ZCBXb3Jrc3BhY2UiLCAjIFN0ZXAgMw0KICAgICAgcGEgPT0gIkNsb3VkIiAmIGNvbnZlcnNpb24gPT0gIlR5cGUgMTQyNTc4MDMgKEVudGVycHJpc2UgLSBBcHBzIC0gU2lnbnVwIENvbmZpcm0gLSBVbmlxdWUpIiB+ICJDbG91ZCBHQ1AiLCAjIFN0ZXAgMw0KICAgICAgcGEgPT0gIlByb2plY3QgRmkiIH4gIkdvb2dsZSBGaSIsICMgU3RlcCA0DQogICAgICBwYSA9PSAiR29vZ2xlIENocm9tZSIgfiAiQ2hyb21lIiwNCiAgICAgIFRSVUUgfiBwYQ0KICAgICkNCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIHBhcnNlZF90eXBlID0gcGFyc2VfbnVtYmVyKGNvbnZlcnNpb24pLA0KICAgIGdyb3VwZWRfY29udmVyc2lvbiA9IGNhc2Vfd2hlbigNCiAgICAgIGNvbnZlcnNpb24gJWluJSBjKCJDaHJvbWVib29rIE1pY3Jvc2l0ZSBSZWZlcnJhbCBDbGlja3MgUTQgMjAxNSIsICJUeXBlIDI1MTQyMjcyOSAoQ2hyb21lYm9va3MgTWljcm9zaXRlIFJlZmVycmFsIENsaWNrcyAoUTQgMjAxNykpIikgfiAiQ2hyb21lYm9vayBSZWZlcnJhbHMiLA0KICAgICAgY29udmVyc2lvbiAlaW4lIGMoIkRlc2t0b3AgRG93bmxvYWRzIiwgIlR5cGUgMTE1NDE1NDcgKERlc2t0b3AgRG93bmxvYWQpIikgfg0KICAgICAgICAiRGVza3RvcCBEb3dubG9hZHMiLA0KICAgICAgcGEgPT0gIlBpeGVsIiB+ICJNb2JpbGUgQ29udmVyc2lvbnMiLA0KICAgICAgcGEgPT0gIkRTTSIgfiAiTm9uLU1vYmlsZSBEZXZpY2UgQ29udmVyc2lvbnMiLA0KICAgICAgY29udmVyc2lvbiA9PSAiVHlwZSAzMDI5ODI5NTQgKExlbmEgLSBQIExlYWQpIiB+ICJMZW5hIFAgTGVhZCIsDQogICAgICBjb252ZXJzaW9uID09ICJUeXBlIDI4ODM0NzAwOCAoTEVOQSAtIEIgTGVhZCkiIH4gIkxlbmEgQiBMZWFkIiwNCiAgICAgIGNvbnZlcnNpb24gPT0gIlR5cGUgMjg4Njk3NjUzIChMRU5BIC0gUSBMZWFkKSIgfiAiTGVuYSBRIExlYWQiLA0KICAgICAgcGFyc2VkX3R5cGUgJWluJSBjKDE4MTI4Mzk5MywgODU1NTA4Njg2KSB+ICJXb3Jrc3BhY2UgRnJlZSBUcmlhbCBTdGFydCIsDQogICAgICBwYXJzZWRfdHlwZSA9PSAzMzA3NTU2NDEgfiAiTWljcm9zaXRlIENvbnZlcnNpb25zIiwNCiAgICAgIHBhcnNlZF90eXBlID09IDE0MjU3ODAzIH4gIkVudGVycHJpc2UgU2lnbnVwcyIsDQogICAgICBwYXJzZWRfdHlwZSA9PSAyODk2ODA3MTIgfiAiR29vZ2xlKGlPcykgRmlyc3QgT3BlbiIsDQogICAgICBwYXJzZWRfdHlwZSA9PSAyNTY1MjI5NDIgfiAiWW91VHViZSBUViAtIFdlYiAtIFRyaWFsIFN0YXJ0IiwNCiAgICAgIHBhcnNlZF90eXBlICVpbiUgYyg0NTIzOTE1MzQsIDIyMTQ5NzgzMywgMjc3MTUwMDc0KSB+ICJUcmlhbCBTaWdudXBzIENvbXBsZXRlIiwNCiAgICAgIFRSVUUgfiBjb252ZXJzaW9uDQogICAgKSwNCiAgICBwYSA9IGNhc2Vfd2hlbigNCiAgICAgIGNvbnZlcnNpb24gPT0gIlR5cGUgMjg4Njk3NjUzIChMRU5BIC0gUSBMZWFkKSIgfiAiU01CLVFMZWFkIiwNCiAgICAgIFRSVUUgfiBwYQ0KICAgICkNCiAgKSAlPiUNCiAgZmlsdGVyKGFic29sdXRlX2xpZnQgPiAwKQ0KDQoNCiMgYWxsLmVxdWFsKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlLEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF92MykNCmBgYA0KDQojIENyZWF0ZSBBbGwgUmVzcG9uc2UgQ3VydmVzIG9ubHkgbm9ybWFsIHBvd2Vycw0KDQojIyBGb2xkZXIgZm9yIGFsbCBPdXRwdXQgYW5kIHNjcmlwdHMNCg0KYGBge3J9DQpmb2xkZXJfbmFtZSA8LSBwYXN0ZTAoIk91dHB1dC8iLCAib3V0cHV0ZmlsZXNfIiwgU3lzLkRhdGUoKSwgIl8iLCAiUnVuMSIsICIvIikNCmRpci5jcmVhdGUoZm9sZGVyX25hbWUpICMgaXQgd2lsbCB0aHJvdyBhIHdhcm5pbmcgaWYgZm9sZGVyIGV4aXN0cw0KDQojIGZpbGUuc291cmNlczIgPC0gbGlzdC5maWxlcyhwYXRoID0gIk91dHB1dC9vdXRwdXRmaWxlc18yMDIyLTEwLTE0X1J1bjEvLyIsIHBhdHRlcm4gPSIuaHRtbHwucG5nIiwgZnVsbC5uYW1lcyA9IFRSVUUpDQpmaWxlLnNvdXJjZXMgPC0gbGlzdC5maWxlcyhwYXRoID0gIlJTY3JpcHRzLyIsIHBhdHRlcm4gPSAiKi5SIiwgZnVsbC5uYW1lcyA9IFRSVUUpDQpzYXBwbHkoZmlsZS5zb3VyY2VzLCBzb3VyY2UsIC5HbG9iYWxFbnYpDQpgYGANCg0KIyMgQ2hlY2sgcGFyYW1ldGVycw0KDQpgYGB7cn0NCg0KIyMjIHBvd2VycyB0byB0cnkNCnBvd2VycyA8LSBzZXEoMC4xLCAwLjksIGJ5ID0gMC4wMSkNCnBvd2VyczIgPC0gMQ0KDQojIyMgUG93ZXJzIHRvIFRyeQ0KI3Bvd2VycyA8LSBzZXEoMC4xLCAwLjksIGJ5ID0gMC4wMSkNCiNwb3dlcnMyIDwtc2VxKDEuNSwzLCBieSA9IDAuMjUpDQoNCg0KIyMjIExhbWJkYSBwYXJhbWV0ZXJzDQpwYXJhbWV0ZXJzIDwtIGMoDQogICMgIHNlcSgwLjEsIDIsIGJ5ID0wLjEpICwgIHNlcSgyLCA1LCAwLjUpICwNCiAgc2VxKDUsIDI5LCAxKQ0KICAsc2VxKDMwLCAxMDIsIDQpDQogICxzZXEoMTEwLCAxMDAwLCAxNSkNCiAgLHNlcSgxMDAwLCAxMDAyMCwgNTAwKQ0KKQ0KDQojIyMgZWxhc3RpY25ldCBwYXJhbWV0ZXJzDQphbHBoYV9wYXJhbWV0ZXJzIDwtIGMoc2VxKDAsIDEsIDAuMjUpKQ0KDQojIEZvciBUZXN0aW5nIFB1cnBvc2VzDQojYWxwaGFfcGFyYW1ldGVycyA8LSBjKHNlcSgxLCAxLCAxKSkNCg0KYGBgDQoNCiMjIFRlc3RpbmcgRGlmZmVyZW50IE1vZGVsIFR5cGVzDQoNCiMjIyBDaHJvbWUNCg0KIyMjIyBEYXRhIFJlYWRpbg0KDQpgYGB7cn0NCg0Kc3RhcnRfdGltZSA8LSBTeXMudGltZSgpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZV9wcmUgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGUgJT4lDQogIGZpbHRlcihwYSA9PSAiQ2hyb21lIikgJT4lDQogIG11dGF0ZSgNCiAgICBpZDIgPSByb3dfbnVtYmVyKCkNCiAgKQ0KDQpkZl90ZXN0IDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZV9wcmUgJT4lDQogIHNlbGVjdCgNCiAgICByZWdpb25fdjIsIGNvdW50cnksIGNoYW5uZWwsIHRhY3RpYywNCiAgICBjb3N0X3NwZW50X29uX2V4cG9zZWRfZ3JvdXA6YWJzb2x1dGVfbGlmdA0KICApDQoNCmlzb19jaHJvbWUgPC0gaXNvbGF0aW9uRm9yZXN0JG5ldyhzYW1wbGVfc2l6ZSA9IG5yb3coZGZfdGVzdCksIG51bV90cmVlcyA9IDEwMDAwLCBzZWVkID0gMTE1MykNCg0KaXNvX2Nocm9tZSRmaXQoZGZfdGVzdCkNCg0Kc2NvcmVzX3RyYWluIDwtIGRmX3Rlc3QgJT4lDQogIGlzb19jaHJvbWUkcHJlZGljdCgpICU+JQ0KICBhcnJhbmdlKGRlc2MoYW5vbWFseV9zY29yZSkpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZV9wcmUyIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZV9wcmUgJT4lDQogIGxlZnRfam9pbihzY29yZXNfdHJhaW4sIGJ5ID0gYygiaWQyIiA9ICJpZCIpKSAlPiUgDQogIGZpbHRlcihhdmVyYWdlX2RlcHRoID4gMykNCg0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9jaHJvbWUgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfY2hyb21lX3ByZTIgJT4lDQogIG5hbWVkX2dyb3VwX3NwbGl0KHRhY3RpYykNCmBgYA0KDQojIyMjIFJ1biBNb2RlbA0KDQpgYGB7ciwgd2FybmluZyA9IGZhbHNlfQ0KDQoNCmZpdHNfbm9uX3NlYXJjaF9jaHJvbWUgPC0gbW9kZWxfd3JhcHBlcl9mdW5jdGlvbihkZiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZSxwb2x5X2luZCA9IDApDQoNCmJlc3RfaW5kX25vbl9zZWFyY2hfY2hyb21lIDwtIA0KICBsYXBwbHkoMTpsZW5ndGgoRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfY2hyb21lKSwgYmVzdF9pbmRfZnVuY3Rpb24sZGYgPSBmaXRzX25vbl9zZWFyY2hfY2hyb21lLA0KICAgICAgICAgZGYyID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfY2hyb21lKSANCg0KY29lZl9ub25fc2VhcmNoX2Nocm9tZSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX2Nocm9tZSAlPiUgYmluZF9yb3dzICNtYWtlIGEgbWF0cml4IG9mIGFsbCBjb2Vmcw0KDQpiZXN0X2ZpdF9ub25fc2VhcmNoX2Nocm9tZSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX2Nocm9tZSAlPiUNCiAgc2V0X25hbWVzKG5hbWVzX2Z1bmN0aW9uKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZV9wcmUsIHRhY3RpYykpICANCmBgYA0KDQojIyMjIENyZWF0ZSBHcmFwaCBPYmplY3QNCg0KYGBge3J9DQpncmFwaF9saXN0X2Nocm9tZSA8LSBsYXBwbHkoMTpsZW5ndGgoYmVzdF9maXRfbm9uX3NlYXJjaF9jaHJvbWUpLCBncmFwaGluZ19mdW5jdGlvbjQsIGRmMSA9IGJlc3RfZml0X25vbl9zZWFyY2hfY2hyb21lLCBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9jaHJvbWUpDQpgYGANCg0KYGBge3J9DQplbmRfdGltZSA8LSBTeXMudGltZSgpDQoNCnRpbWVfY2hyb21lID0gZW5kX3RpbWUgLSBzdGFydF90aW1lDQoNCnRpbWVfY2hyb21lDQpgYGANCg0KIyMjIENsb3VkDQoNCiMjIyMgRGF0YSBSZWFkaW4NCg0KYGBge3J9DQpzdGFydF90aW1lIDwtIFN5cy50aW1lKCkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfY2xvdWRfcHJlIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlICU+JQ0KICBmaWx0ZXIocGEgJWluJSBjKCJDbG91ZCBHQ1AiLCAiQ2xvdWQgV29ya3NwYWNlIikpICU+JQ0KICBtdXRhdGUoDQogICAgcGEgPSAiQ2xvdWQiLA0KICAgIHBhMiA9ICJDbG91ZCAtIEFsbCBDaGFubmVsIg0KICApICU+JQ0KICBtdXRhdGUoDQogICAgaWQyID0gcm93X251bWJlcigpDQogICkNCg0KZGZfdGVzdCA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9jbG91ZF9wcmUgJT4lDQogICMgc2VsZWN0KC1zdHVkeV9pZCwgLWlkMiwgLXJlZ2lvbiwgLXNjYWxpbmdfZmFjdG9yLCAtcXVhcnRlciwgLXBhLCAtc3R1ZHlfbmFtZSkNCiAgc2VsZWN0KA0KICAgIHJlZ2lvbl92MiwgY291bnRyeSwgY2hhbm5lbCwgdGFjdGljLA0KICAgICMgdHJlYXRtZW50X3VzZXJfY291bnQ6Y29udHJvbCwNCiAgICBjb3N0X3NwZW50X29uX2V4cG9zZWRfZ3JvdXA6YWJzb2x1dGVfbGlmdCwgcGFyc2VkX3R5cGUNCiAgKQ0KDQppc29fY2xvdWQgPC0gaXNvbGF0aW9uRm9yZXN0JG5ldyhzYW1wbGVfc2l6ZSA9IG5yb3coZGZfdGVzdCksIG51bV90cmVlcyA9IDEwMDAwLCBzZWVkID0gMTE1MykNCg0KaXNvX2Nsb3VkJGZpdChkZl90ZXN0KQ0KDQpzY29yZXNfdHJhaW4gPC0gZGZfdGVzdCAlPiUNCiAgaXNvX2Nsb3VkJHByZWRpY3QoKSAlPiUNCiAgYXJyYW5nZShkZXNjKGFub21hbHlfc2NvcmUpKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9jbG91ZF9wcmUyIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkX3ByZSAlPiUNCiAgbGVmdF9qb2luKHNjb3Jlc190cmFpbiwgYnkgPSBjKCJpZDIiID0gImlkIikpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkX3ByZTIgJT4lDQogIG5hbWVkX2dyb3VwX3NwbGl0KHBhMikNCg0KYGBgDQoNCiMjIyMgUnVuIE1vZGVsDQoNCmBgYHtyLCB3YXJuaW5nID0gZmFsc2V9DQpmaXRzX25vbl9zZWFyY2hfY2xvdWQgPC0gbW9kZWxfd3JhcHBlcl9mdW5jdGlvbihkZiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkLHBvbHlfaW5kID0gMCkNCg0KYmVzdF9pbmRfbm9uX3NlYXJjaF9jbG91ZCA8LSANCiAgbGFwcGx5KDE6bGVuZ3RoKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkKSwgYmVzdF9pbmRfZnVuY3Rpb24sZGYgPSBmaXRzX25vbl9zZWFyY2hfY2xvdWQsDQogICAgICAgICBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9jbG91ZCkgDQoNCmNvZWZfbm9uX3NlYXJjaF9jbG91ZCA8LSBiZXN0X2luZF9ub25fc2VhcmNoX2Nsb3VkICU+JSBiaW5kX3Jvd3MgI21ha2UgYSBtYXRyaXggb2YgYWxsIGNvZWZzDQoNCmJlc3RfZml0X25vbl9zZWFyY2hfY2xvdWQgPC0gYmVzdF9pbmRfbm9uX3NlYXJjaF9jbG91ZCAlPiUNCiAgc2V0X25hbWVzKG5hbWVzX2Z1bmN0aW9uKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkX3ByZSwgcGEyKSkgIA0KYGBgDQoNCiMjIyMgQ3JlYXRlIEdyYXBoIE9iamVjdA0KDQpgYGB7cn0NCmdyYXBoX2xpc3RfY2xvdWQgPC0gbGFwcGx5KDE6bGVuZ3RoKGJlc3RfZml0X25vbl9zZWFyY2hfY2xvdWQpLCBncmFwaGluZ19mdW5jdGlvbjQsIGRmMSA9IGJlc3RfZml0X25vbl9zZWFyY2hfY2xvdWQsIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkKQ0KYGBgDQoNCg0KYGBge3J9DQplbmRfdGltZSA8LSBTeXMudGltZSgpDQoNCnRpbWVfY2xvdWQgPSBlbmRfdGltZSAtIHN0YXJ0X3RpbWUNCmBgYA0KDQojIyMgWW91VHViZQ0KDQojIyMjIERhdGEgUmVhZGluDQoNCmBgYHtyfQ0KDQpzdGFydF90aW1lIDwtIFN5cy50aW1lKCkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfeW91dHViZV9wcmUgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGUgJT4lDQogIGZpbHRlcihwYSAlaW4lIGMoIllvdVR1YmUgVFYiLCAiWVRNUCIpKSAlPiUNCiAgbXV0YXRlKA0KICAgIHBhID0gIllvdVR1YmUiLA0KICAgIHBhMiA9ICJZb3VUdWJlIg0KICApICU+JQ0KICAjICBmaWx0ZXIoYWJzb2x1dGVfbGlmdCA8IDUwMDApICU+JQ0KICBtdXRhdGUoDQogICAgaWQyID0gcm93X251bWJlcigpDQogICkNCg0KZGZfdGVzdCA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV95b3V0dWJlX3ByZSAlPiUNCiAgIyBzZWxlY3QoLXN0dWR5X2lkLCAtaWQyLCAtcmVnaW9uLCAtc2NhbGluZ19mYWN0b3IsIC1xdWFydGVyLCAtcGEsIC1zdHVkeV9uYW1lKQ0KICBzZWxlY3QoDQogICAgcmVnaW9uX3YyLCBjb3VudHJ5LCBjaGFubmVsLCB0YWN0aWMsDQogICAgIyB0cmVhdG1lbnRfdXNlcl9jb3VudDpjb250cm9sLA0KICAgIGNvc3Rfc3BlbnRfb25fZXhwb3NlZF9ncm91cDphYnNvbHV0ZV9saWZ0LCBwYXJzZWRfdHlwZQ0KICApDQoNCmlzb195dCA8LSBpc29sYXRpb25Gb3Jlc3QkbmV3KHNhbXBsZV9zaXplID0gbnJvdyhkZl90ZXN0KSwgbnVtX3RyZWVzID0gMTAwMDAsIHNlZWQgPSAxMTUzKQ0KDQppc29feXQkZml0KGRmX3Rlc3QpDQoNCnNjb3Jlc190cmFpbiA8LSBkZl90ZXN0ICU+JQ0KICBpc29feXQkcHJlZGljdCgpICU+JQ0KICBhcnJhbmdlKGRlc2MoYW5vbWFseV9zY29yZSkpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3lvdXR1YmVfcHJlMiA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV95b3V0dWJlX3ByZSAlPiUNCiAgbGVmdF9qb2luKHNjb3Jlc190cmFpbiwgYnkgPSBjKCJpZDIiID0gImlkIikpICU+JQ0KICBmaWx0ZXIoYXZlcmFnZV9kZXB0aCA+IDMuODkpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3lvdXR1YmUgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfeW91dHViZV9wcmUyICU+JQ0KICBuYW1lZF9ncm91cF9zcGxpdChyZWdpb25fdjIpDQpgYGANCg0KIyMjIyBSdW4gTW9kZWwNCg0KYGBge3IsIHdhcm5pbmcgPSBmYWxzZX0NCmZpdHNfbm9uX3NlYXJjaF95b3V0dWJlIDwtIG1vZGVsX3dyYXBwZXJfZnVuY3Rpb24oZGYgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV95b3V0dWJlLHBvbHlfaW5kID0gMCkNCg0KYmVzdF9pbmRfbm9uX3NlYXJjaF95b3V0dWJlIDwtIA0KICBsYXBwbHkoMTpsZW5ndGgoRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfeW91dHViZSksIGJlc3RfaW5kX2Z1bmN0aW9uLGRmID0gZml0c19ub25fc2VhcmNoX3lvdXR1YmUsDQogICAgICAgICBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV95b3V0dWJlKSANCg0KY29lZl9ub25fc2VhcmNoX3lvdXR1YmUgPC0gYmVzdF9pbmRfbm9uX3NlYXJjaF95b3V0dWJlICU+JSBiaW5kX3Jvd3MgI21ha2UgYSBtYXRyaXggb2YgYWxsIGNvZWZzDQoNCmJlc3RfZml0X25vbl9zZWFyY2hfeW91dHViZSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX3lvdXR1YmUgJT4lDQogIHNldF9uYW1lcyhuYW1lc19mdW5jdGlvbihGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV95b3V0dWJlX3ByZSwgcGEyKSkgIA0KYGBgDQoNCiMjIyMgQ3JlYXRlIEdyYXBoIE9iamVjdA0KDQpgYGB7cn0NCmdyYXBoX2xpc3RfeW91dHViZSA8LSBsYXBwbHkoMTpsZW5ndGgoYmVzdF9maXRfbm9uX3NlYXJjaF95b3V0dWJlKSwgZ3JhcGhpbmdfZnVuY3Rpb240LCBkZjEgPSBiZXN0X2ZpdF9ub25fc2VhcmNoX3lvdXR1YmUsIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3lvdXR1YmUpDQpgYGANCg0KDQpgYGB7cn0NCmVuZF90aW1lIDwtIFN5cy50aW1lKCkNCg0KdGltZV95b3V0dWJlID0gZW5kX3RpbWUgLSBzdGFydF90aW1lDQpgYGANCg0KDQojIyMgRFNNDQoNCiMjIyMgRGF0YSBSZWFkaW4NCg0KYGBge3J9DQoNCnN0YXJ0X3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9kc21fcHJlIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlICU+JQ0KICBmaWx0ZXIocGEgPT0gIkRTTSIpICU+JQ0KICBmaWx0ZXIocmVnaW9uX3YyICE9ICJBUEFDIikgJT4lDQogICMgZmlsdGVyKGFic29sdXRlX2xpZnQgPCAxMDAwKSAjICU+JQ0KICAjIGZpbHRlcihzdHVkeV9pZCAhPSAnNjI5NzQyMCcpICMlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9JzE0OTE2MTcxMScpICU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0gJzE0ODYxMzAwMicpICU+JQ0KICAjIGZpbHRlcihzdHVkeV9pZCAhPSczMjg0NjI1JykgJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPSczMzI5MTMxJykNCiAgbXV0YXRlKA0KICAgIGlkMiA9IHJvd19udW1iZXIoKQ0KICApDQoNCmRmX3Rlc3QgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX3ByZSAlPiUNCiAgIyBzZWxlY3QoLXN0dWR5X2lkLCAtaWQyLCAtcmVnaW9uLCAtc2NhbGluZ19mYWN0b3IsIC1xdWFydGVyLCAtcGEsIC1zdHVkeV9uYW1lKQ0KICBzZWxlY3QoDQogICAgcmVnaW9uX3YyLCBjb3VudHJ5LCBjaGFubmVsLCB0YWN0aWMsDQogICAgIyB0cmVhdG1lbnRfdXNlcl9jb3VudDpjb250cm9sLA0KICAgIGNvc3Rfc3BlbnRfb25fZXhwb3NlZF9ncm91cDphYnNvbHV0ZV9saWZ0DQogICkNCg0KaXNvX2RzbSA8LSBpc29sYXRpb25Gb3Jlc3QkbmV3KHNhbXBsZV9zaXplID0gbnJvdyhkZl90ZXN0KSwgbnVtX3RyZWVzID0gMTAwMDAsIHNlZWQgPSAxMTUyKQ0KDQppc29fZHNtJGZpdChkZl90ZXN0KQ0KDQpzY29yZXNfdHJhaW4gPC0gZGZfdGVzdCAlPiUNCiAgaXNvX2RzbSRwcmVkaWN0KCkgJT4lDQogIGFycmFuZ2UoZGVzYyhhbm9tYWx5X3Njb3JlKSkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX3ByZTIgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX3ByZSAlPiUNCiAgbGVmdF9qb2luKHNjb3Jlc190cmFpbiwgYnkgPSBjKCJpZDIiID0gImlkIikpICU+JQ0KICBmaWx0ZXIoYXZlcmFnZV9kZXB0aCA+IDUpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbSA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9kc21fcHJlMiAlPiUNCiAgbmFtZWRfZ3JvdXBfc3BsaXQocmVnaW9uX3YyLCBjaGFubmVsKQ0KYGBgDQoNCiMjIyMgUnVuIE1vZGVsDQoNCmBgYHtyLCB3YXJuaW5nID0gZmFsc2V9DQpmaXRzX25vbl9zZWFyY2hfZHNtIDwtIG1vZGVsX3dyYXBwZXJfZnVuY3Rpb24oZGYgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9kc20scG9seV9pbmQgPSAwKQ0KDQpiZXN0X2luZF9ub25fc2VhcmNoX2RzbSA8LSANCiAgbGFwcGx5KDE6bGVuZ3RoKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbSksIGJlc3RfaW5kX2Z1bmN0aW9uLGRmID0gZml0c19ub25fc2VhcmNoX2RzbSwNCiAgICAgICAgIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbSkNCg0KY29lZl9ub25fc2VhcmNoX2RzbSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX2RzbSAlPiUgYmluZF9yb3dzICNtYWtlIGEgbWF0cml4IG9mIGFsbCBjb2Vmcw0KDQpiZXN0X2ZpdF9ub25fc2VhcmNoX2RzbSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX2RzbSAlPiUNCiAgc2V0X25hbWVzKG5hbWVzX2Z1bmN0aW9uKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9wcmUsIHJlZ2lvbl92MixjaGFubmVsKSkgIA0KYGBgDQoNCiMjIyMgQ3JlYXRlIEdyYXBoIE9iamVjdA0KDQpgYGB7cn0NCmdyYXBoX2xpc3RfZHNtIDwtIGxhcHBseSgxOmxlbmd0aChiZXN0X2ZpdF9ub25fc2VhcmNoX2RzbSksIGdyYXBoaW5nX2Z1bmN0aW9uNCwgZGYxID0gYmVzdF9maXRfbm9uX3NlYXJjaF9kc20sIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbSkNCmBgYA0KDQoNCmBgYHtyfQ0KZW5kX3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQp0aW1lX2RzbSA9IGVuZF90aW1lIC0gc3RhcnRfdGltZQ0KYGBgDQoNCg0KIyMjIFBpeGVsDQoNCiMjIyMgRGF0YSBSZWFkaW4NCg0KYGBge3J9DQoNCnN0YXJ0X3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9waXhlbF9wcmUgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGUgJT4lDQogIGZpbHRlcihwYSA9PSAiUGl4ZWwiKSAlPiUNCiAgbXV0YXRlKA0KICAgIHBhMiA9ICJQaXhlbCAtIEFsbCBDaGFubmVsIg0KICApICU+JQ0KICAjICAgZmlsdGVyKGFic29sdXRlX2xpZnQgPCAxMDAwKSAgJT4lDQogICMgZmlsdGVyKHN0dWR5X2lkICE9ICc2Mjk3NDIwJykgIyU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0nMTQ5MTYxNzExJykgJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPSAnMTQ4NjEzMDAyJykgJT4lDQogICMgZmlsdGVyKHN0dWR5X2lkICE9JzMyODQ2MjUnKSAlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9JzMzMjkxMzEnKQ0KICBtdXRhdGUoDQogICAgaWQyID0gcm93X251bWJlcigpDQogICkNCg0KZGZfdGVzdCA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9waXhlbF9wcmUgJT4lDQogICMgc2VsZWN0KC1zdHVkeV9pZCwgLWlkMiwgLXJlZ2lvbiwgLXNjYWxpbmdfZmFjdG9yLCAtcXVhcnRlciwgLXBhLCAtc3R1ZHlfbmFtZSkNCiAgc2VsZWN0KA0KICAgIHJlZ2lvbl92MiwgY291bnRyeSwgY2hhbm5lbCwgdGFjdGljLA0KICAgICMgdHJlYXRtZW50X3VzZXJfY291bnQ6Y29udHJvbCwNCiAgICBjb3N0X3NwZW50X29uX2V4cG9zZWRfZ3JvdXA6YWJzb2x1dGVfbGlmdA0KICApDQoNCmlzb19waXhlbCA8LSBpc29sYXRpb25Gb3Jlc3QkbmV3KHNhbXBsZV9zaXplID0gbnJvdyhkZl90ZXN0KSwgbnVtX3RyZWVzID0gMTAwMDAsIHNlZWQgPSAxMTUyKQ0KDQppc29fcGl4ZWwkZml0KGRmX3Rlc3QpDQoNCnNjb3Jlc190cmFpbiA8LSBkZl90ZXN0ICU+JQ0KICBpc29fcGl4ZWwkcHJlZGljdCgpICU+JQ0KICBhcnJhbmdlKGRlc2MoYW5vbWFseV9zY29yZSkpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3BpeGVsX3ByZTIgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfcGl4ZWxfcHJlICU+JQ0KICBsZWZ0X2pvaW4oc2NvcmVzX3RyYWluLCBieSA9IGMoImlkMiIgPSAiaWQiKSkgJT4lDQogIGZpbHRlcihhdmVyYWdlX2RlcHRoID4gMy4xKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9waXhlbF9wcmUyDQoNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfcGl4ZWwgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfcGl4ZWxfcHJlMiAlPiUNCiAgbmFtZWRfZ3JvdXBfc3BsaXQocGEyKQ0KYGBgDQoNCiMjIyMgUnVuIE1vZGVsDQoNCmBgYHtyLCB3YXJuaW5nID0gZmFsc2V9DQpmaXRzX25vbl9zZWFyY2hfcGl4ZWwgPC0gbW9kZWxfd3JhcHBlcl9mdW5jdGlvbihkZiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3BpeGVsLHBvbHlfaW5kID0gMCkNCg0KYmVzdF9pbmRfbm9uX3NlYXJjaF9waXhlbCA8LSANCiAgbGFwcGx5KDE6bGVuZ3RoKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3BpeGVsKSwgYmVzdF9pbmRfZnVuY3Rpb24sZGYgPSBmaXRzX25vbl9zZWFyY2hfcGl4ZWwsDQogICAgICAgICBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9waXhlbCkgDQoNCmNvZWZfbm9uX3NlYXJjaF9waXhlbCA8LSBiZXN0X2luZF9ub25fc2VhcmNoX3BpeGVsICU+JSBiaW5kX3Jvd3MgI21ha2UgYSBtYXRyaXggb2YgYWxsIGNvZWZzDQoNCmJlc3RfZml0X25vbl9zZWFyY2hfcGl4ZWwgPC0gYmVzdF9pbmRfbm9uX3NlYXJjaF9waXhlbCAlPiUNCiAgc2V0X25hbWVzKG5hbWVzX2Z1bmN0aW9uKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3BpeGVsX3ByZSwgcGEyKSkgIA0KYGBgDQoNCiMjIyMgQ3JlYXRlIEdyYXBoIE9iamVjdA0KDQpgYGB7cn0NCmdyYXBoX2xpc3RfcGl4ZWwgPC0gbGFwcGx5KDE6bGVuZ3RoKGJlc3RfZml0X25vbl9zZWFyY2hfcGl4ZWwpLCBncmFwaGluZ19mdW5jdGlvbjQsIGRmMSA9IGJlc3RfZml0X25vbl9zZWFyY2hfcGl4ZWwsIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3BpeGVsKQ0KYGBgDQoNCg0KYGBge3J9DQplbmRfdGltZSA8LSBTeXMudGltZSgpDQoNCnRpbWVfcGl4ZWwgPSBlbmRfdGltZSAtIHN0YXJ0X3RpbWUNCmBgYA0KDQoNCiMjIyBGaQ0KDQojIyMjIERhdGEgUmVhZGluDQoNCmBgYHtyfQ0KDQpzdGFydF90aW1lIDwtIFN5cy50aW1lKCkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZmlfcHJlIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlICU+JQ0KICBmaWx0ZXIocGEgPT0gIkdvb2dsZSBGaSIpICU+JQ0KICBtdXRhdGUoDQogICAgcGEyID0gIkZpIC0gQWxsIENoYW5uZWwiDQogICkgJT4lDQogICMgICBmaWx0ZXIoYWJzb2x1dGVfbGlmdCA8IDEwMDApICAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0gJzYyOTc0MjAnKSAjJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPScxNDkxNjE3MTEnKSAlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9ICcxNDg2MTMwMDInKSAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzI4NDYyNScpICU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzMyOTEzMScpDQogIG11dGF0ZSgNCiAgICBpZDIgPSByb3dfbnVtYmVyKCkNCiAgKQ0KDQpkZl90ZXN0IDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2ZpX3ByZSAlPiUNCiAgIyBzZWxlY3QoLXN0dWR5X2lkLCAtaWQyLCAtcmVnaW9uLCAtc2NhbGluZ19mYWN0b3IsIC1xdWFydGVyLCAtcGEsIC1zdHVkeV9uYW1lKQ0KICBzZWxlY3QoDQogICAgcmVnaW9uX3YyLCBjb3VudHJ5LCBjaGFubmVsLCB0YWN0aWMsDQogICAgIyB0cmVhdG1lbnRfdXNlcl9jb3VudDpjb250cm9sLA0KICAgIGNvc3Rfc3BlbnRfb25fZXhwb3NlZF9ncm91cDphYnNvbHV0ZV9saWZ0DQogICkNCg0KaXNvX2ZpIDwtIGlzb2xhdGlvbkZvcmVzdCRuZXcoc2FtcGxlX3NpemUgPSBucm93KGRmX3Rlc3QpLCBudW1fdHJlZXMgPSAxMDAwMCwgc2VlZCA9IDExNTIpDQoNCmlzb19maSRmaXQoZGZfdGVzdCkNCg0Kc2NvcmVzX3RyYWluIDwtIGRmX3Rlc3QgJT4lDQogIGlzb19maSRwcmVkaWN0KCkgJT4lDQogIGFycmFuZ2UoZGVzYyhhbm9tYWx5X3Njb3JlKSkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZmlfcHJlMiA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maV9wcmUgJT4lDQogIGxlZnRfam9pbihzY29yZXNfdHJhaW4sIGJ5ID0gYygiaWQyIiA9ICJpZCIpKSAlPiUNCiAgZmlsdGVyKGF2ZXJhZ2VfZGVwdGggPiA0Ljc1KQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maV9wcmUyDQoNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZmkgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZmlfcHJlMiAlPiUNCiAgbmFtZWRfZ3JvdXBfc3BsaXQoY2hhbm5lbCkNCmBgYA0KDQojIyMjIFJ1biBNb2RlbA0KDQpgYGB7ciwgd2FybmluZyA9IGZhbHNlfQ0KZml0c19ub25fc2VhcmNoX2ZpIDwtIG1vZGVsX3dyYXBwZXJfZnVuY3Rpb24oZGYgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maSxwb2x5X2luZCA9IDApDQoNCmJlc3RfaW5kX25vbl9zZWFyY2hfZmkgPC0gDQogIGxhcHBseSgxOmxlbmd0aChGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maSksIGJlc3RfaW5kX2Z1bmN0aW9uLGRmID0gZml0c19ub25fc2VhcmNoX2ZpLA0KICAgICAgICAgZGYyID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZmkpIA0KDQpjb2VmX25vbl9zZWFyY2hfZmkgPC0gYmVzdF9pbmRfbm9uX3NlYXJjaF9maSAlPiUgYmluZF9yb3dzICNtYWtlIGEgbWF0cml4IG9mIGFsbCBjb2Vmcw0KDQpiZXN0X2ZpdF9ub25fc2VhcmNoX2ZpIDwtIGJlc3RfaW5kX25vbl9zZWFyY2hfZmkgJT4lDQogIHNldF9uYW1lcyhuYW1lc19mdW5jdGlvbihGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maV9wcmUsIHBhMikpICANCmBgYA0KDQojIyMjIENyZWF0ZSBHcmFwaCBPYmplY3QNCg0KYGBge3J9DQpncmFwaF9saXN0X2ZpIDwtIGxhcHBseSgxOmxlbmd0aChiZXN0X2ZpdF9ub25fc2VhcmNoX2ZpKSwgZ3JhcGhpbmdfZnVuY3Rpb240LCBkZjEgPSBiZXN0X2ZpdF9ub25fc2VhcmNoX2ZpLCBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maSkNCmBgYA0KDQoNCmBgYHtyfQ0KZW5kX3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQp0aW1lX2ZpID0gZW5kX3RpbWUgLSBzdGFydF90aW1lDQpgYGANCg0KDQojIyMgU01CIC0gUUxlYWRzDQoNCiMjIyMgRGF0YSBSZWFkaW4NCg0KYGBge3J9DQoNCnN0YXJ0X3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9zbWJxX3ByZSA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZSAlPiUNCiAgZmlsdGVyKGdyb3VwZWRfY29udmVyc2lvbiA9PSAnTGVuYSBRIExlYWQnKSAlPiUNCiAgbXV0YXRlKA0KICAgIHBhMiA9ICJTTUIgLSBRLUxlYWQiDQogICkgJT4lDQogICMgICBmaWx0ZXIoYWJzb2x1dGVfbGlmdCA8IDEwMDApICAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0gJzYyOTc0MjAnKSAjJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPScxNDkxNjE3MTEnKSAlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9ICcxNDg2MTMwMDInKSAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzI4NDYyNScpICU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzMyOTEzMScpDQogIG11dGF0ZSgNCiAgICBpZDIgPSByb3dfbnVtYmVyKCkNCiAgKQ0KDQpkZl90ZXN0IDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYnFfcHJlICU+JQ0KICAjIHNlbGVjdCgtc3R1ZHlfaWQsIC1pZDIsIC1yZWdpb24sIC1zY2FsaW5nX2ZhY3RvciwgLXF1YXJ0ZXIsIC1wYSwgLXN0dWR5X25hbWUpDQogIHNlbGVjdCgNCiAgICByZWdpb25fdjIsIGNvdW50cnksIGNoYW5uZWwsIHRhY3RpYywNCiAgICAjIHRyZWF0bWVudF91c2VyX2NvdW50OmNvbnRyb2wsDQogICAgY29zdF9zcGVudF9vbl9leHBvc2VkX2dyb3VwOmFic29sdXRlX2xpZnQNCiAgKQ0KDQppc29fc21icSA8LSBpc29sYXRpb25Gb3Jlc3QkbmV3KHNhbXBsZV9zaXplID0gbnJvdyhkZl90ZXN0KSwgbnVtX3RyZWVzID0gMTAwMDAsIHNlZWQgPSAxMTUyKQ0KDQppc29fc21icSRmaXQoZGZfdGVzdCkNCg0Kc2NvcmVzX3RyYWluIDwtIGRmX3Rlc3QgJT4lDQogIGlzb19zbWJxJHByZWRpY3QoKSAlPiUNCiAgYXJyYW5nZShkZXNjKGFub21hbHlfc2NvcmUpKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9zbWJxX3ByZTIgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21icV9wcmUgJT4lDQogIGxlZnRfam9pbihzY29yZXNfdHJhaW4sIGJ5ID0gYygiaWQyIiA9ICJpZCIpKSAlPiUgDQogIGZpbHRlcihhdmVyYWdlX2RlcHRoID4gMSkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21icSA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9zbWJxX3ByZTIgJT4lDQogIG5hbWVkX2dyb3VwX3NwbGl0KHBhMikNCmBgYA0KDQojIyMjIFJ1biBNb2RlbA0KDQpgYGB7ciwgd2FybmluZyA9IGZhbHNlfQ0KZml0c19ub25fc2VhcmNoX3NtYnEgPC0gbW9kZWxfd3JhcHBlcl9mdW5jdGlvbihkZiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYnEscG9seV9pbmQgPSAwKQ0KDQpiZXN0X2luZF9ub25fc2VhcmNoX3NtYnEgPC0gDQogIGxhcHBseSgxOmxlbmd0aChGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9zbWJxKSwgYmVzdF9pbmRfZnVuY3Rpb24sZGYgPSBmaXRzX25vbl9zZWFyY2hfc21icSwNCiAgICAgICAgIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYnEpIA0KDQpjb2VmX25vbl9zZWFyY2hfc21icSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX3NtYnEgJT4lIGJpbmRfcm93cyAjbWFrZSBhIG1hdHJpeCBvZiBhbGwgY29lZnMNCg0KYmVzdF9maXRfbm9uX3NlYXJjaF9zbWJxIDwtIGJlc3RfaW5kX25vbl9zZWFyY2hfc21icSAlPiUNCiAgc2V0X25hbWVzKG5hbWVzX2Z1bmN0aW9uKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYnFfcHJlLCBwYTIpKSAgDQpgYGANCg0KIyMjIyBDcmVhdGUgR3JhcGggT2JqZWN0DQoNCmBgYHtyfQ0KZ3JhcGhfbGlzdF9zbWJxIDwtIGxhcHBseSgxOmxlbmd0aChiZXN0X2ZpdF9ub25fc2VhcmNoX3NtYnEpLCBncmFwaGluZ19mdW5jdGlvbjQsIGRmMSA9IGJlc3RfZml0X25vbl9zZWFyY2hfc21icSwgZGYyID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21icSkNCmBgYA0KDQoNCmBgYHtyfQ0KZW5kX3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQp0aW1lX3NtYnEgPSBlbmRfdGltZSAtIHN0YXJ0X3RpbWUNCmBgYA0KDQoNCiMjIyBTTUIgLSBCTGVhZHMNCg0KIyMjIyBEYXRhIFJlYWRpbg0KDQpgYGB7cn0NCg0Kc3RhcnRfdGltZSA8LSBTeXMudGltZSgpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYmJfcHJlIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlICU+JQ0KICBmaWx0ZXIocGEgPT0gIlNNQiIgJiBncm91cGVkX2NvbnZlcnNpb24gPT0gJ0xlbmEgQiBMZWFkJykgJT4lDQogIG11dGF0ZSgNCiAgICBwYTIgPSAiU01CIC0gQi1MZWFkIg0KICApICU+JQ0KICAjICAgZmlsdGVyKGFic29sdXRlX2xpZnQgPCAxMDAwKSAgJT4lDQogICMgZmlsdGVyKHN0dWR5X2lkICE9ICc2Mjk3NDIwJykgIyU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0nMTQ5MTYxNzExJykgJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPSAnMTQ4NjEzMDAyJykgJT4lDQogICMgZmlsdGVyKHN0dWR5X2lkICE9JzMyODQ2MjUnKSAlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9JzMzMjkxMzEnKQ0KICBtdXRhdGUoDQogICAgaWQyID0gcm93X251bWJlcigpDQogICkNCg0KZGZfdGVzdCA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9zbWJiX3ByZSAlPiUNCiAgIyBzZWxlY3QoLXN0dWR5X2lkLCAtaWQyLCAtcmVnaW9uLCAtc2NhbGluZ19mYWN0b3IsIC1xdWFydGVyLCAtcGEsIC1zdHVkeV9uYW1lKQ0KICBzZWxlY3QoDQogICAgcmVnaW9uX3YyLCBjb3VudHJ5LCBjaGFubmVsLCB0YWN0aWMsDQogICAgIyB0cmVhdG1lbnRfdXNlcl9jb3VudDpjb250cm9sLA0KICAgIGNvc3Rfc3BlbnRfb25fZXhwb3NlZF9ncm91cDphYnNvbHV0ZV9saWZ0DQogICkNCg0KaXNvX3NtYmIgPC0gaXNvbGF0aW9uRm9yZXN0JG5ldyhzYW1wbGVfc2l6ZSA9IG5yb3coZGZfdGVzdCksIG51bV90cmVlcyA9IDEwMDAwLCBzZWVkID0gMTE1MikNCg0KaXNvX3NtYmIkZml0KGRmX3Rlc3QpDQoNCnNjb3Jlc190cmFpbiA8LSBkZl90ZXN0ICU+JQ0KICBpc29fc21iYiRwcmVkaWN0KCkgJT4lDQogIGFycmFuZ2UoZGVzYyhhbm9tYWx5X3Njb3JlKSkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYl9wcmUyIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYmJfcHJlICU+JQ0KICBsZWZ0X2pvaW4oc2NvcmVzX3RyYWluLCBieSA9IGMoImlkMiIgPSAiaWQiKSkgJT4lIA0KICBmaWx0ZXIoYXZlcmFnZV9kZXB0aCA+IDQpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYmIgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYl9wcmUyICU+JQ0KICBuYW1lZF9ncm91cF9zcGxpdChjaGFubmVsKQ0KYGBgDQoNCiMjIyMgUnVuIE1vZGVsDQoNCmBgYHtyLCB3YXJuaW5nID0gZmFsc2V9DQpmaXRzX25vbl9zZWFyY2hfc21iYiA8LSBtb2RlbF93cmFwcGVyX2Z1bmN0aW9uKGRmID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYixwb2x5X2luZCA9IDApDQoNCmJlc3RfaW5kX25vbl9zZWFyY2hfc21iYiA8LSANCiAgbGFwcGx5KDE6bGVuZ3RoKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYmIpLCBiZXN0X2luZF9mdW5jdGlvbixkZiA9IGZpdHNfbm9uX3NlYXJjaF9zbWJiLA0KICAgICAgICAgZGYyID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYikgDQoNCmNvZWZfbm9uX3NlYXJjaF9zbWJiIDwtIGJlc3RfaW5kX25vbl9zZWFyY2hfc21iYiAlPiUgYmluZF9yb3dzICNtYWtlIGEgbWF0cml4IG9mIGFsbCBjb2Vmcw0KDQpiZXN0X2ZpdF9ub25fc2VhcmNoX3NtYmIgPC0gYmVzdF9pbmRfbm9uX3NlYXJjaF9zbWJiICU+JQ0KICBzZXRfbmFtZXMobmFtZXNfZnVuY3Rpb24oRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYl9wcmUsIGNoYW5uZWwpKSAgDQpgYGANCg0KIyMjIyBDcmVhdGUgR3JhcGggT2JqZWN0DQoNCmBgYHtyfQ0KZ3JhcGhfbGlzdF9zbWJiIDwtIGxhcHBseSgxOmxlbmd0aChiZXN0X2ZpdF9ub25fc2VhcmNoX3NtYmIpLCBncmFwaGluZ19mdW5jdGlvbjQsIGRmMSA9IGJlc3RfZml0X25vbl9zZWFyY2hfc21iYiwgZGYyID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYikNCmBgYA0KDQoNCmBgYHtyfQ0KZW5kX3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQp0aW1lX3NtYmIgPSBlbmRfdGltZSAtIHN0YXJ0X3RpbWUNCmBgYA0KDQojIyBFeHBvcnQgYWxsIGdyYXBoIGxpc3RzDQoNCmBgYHtyfQ0KZ3JhcGhfbmFtZXMgPC0gbWdldChscyhwYXQgPSAnZ3JhcGhfbGlzdF8nKSkNCiAgIA0KZGZfbmFtZXMgPC0gbWdldChzZXRkaWZmKGxzKHBhdHRlcm4gPSAnRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfJyksIGxzKHBhdHRlcm4gPSAicHJlIikpKQ0KDQojcm0oRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfQ2hyb21lLEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX0Nsb3VkLEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX1lvdVR1YmUpDQoNCiNsYXBwbHkoMTpsZW5ndGgoZ3JhcGhfbmFtZXMpLA0KIyAgICAgIGZ1bmN0aW9uKGopIHsNCiNsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXNbW2pdXSksZXhwb3J0X3JwbG90c19mdW5jdGlvbjIsc3RhcnRpbmdfbmFtZSA9ICJOb25fU2VhcmNoXyIsZm9sZGVyX25hbWUgPSBmb2xkZXJfbmFtZSxkZl9saXN0ID0gI2RmX25hbWVzW1tqXV0sZ3JhcGhpbmdfbGlzdCA9IGdyYXBoX25hbWVzW2pdW1sxXV0pDQojICAgICAgfQ0KIyAgICAgICApDQpgYGANCg0KIyMgR3JpZCBvZiBhbGwgUmVzcG9uc2UgQ3VydmVzDQoNClsqU3ViIFBsb3QgRG9jdW1lbnRhdGlvbipdKGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLykNCg0KYGBge3IsIGZpZy5oZWlnaHQ9IDE1LCBlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KbGFwcGx5KDE6bGVuZ3RoKGdyYXBoX25hbWVzKSwNCmZ1bmN0aW9uKGkpew0KICBzdWJwbG90KGdyYXBoX25hbWVzW2ldW1sxXV0sIG5yb3dzID0gbGVuZ3RoKGdyYXBoX25hbWVzW2ldW1sxXV0pKQ0KfQ0KKQ0KDQoNCmxhcHBseSgxOmxlbmd0aChncmFwaF9uYW1lcyksDQpmdW5jdGlvbihpKXsNCiNwMSA9IGdyYXBoX25hbWVzW2ldW1sxXV0NCmRvLmNhbGwoZ3JpZC5hcnJhbmdlLGdyYXBoX25hbWVzW2ldW1sxXV0pDQojcmV0dXJuKGdyaWQuYXJyYW5nZShncm9icyA9IHAxKSkNCn0NCikNCg0KYGBgDQoNCiMjIENvZWYgTWF0cml4DQoNCmBgYHtyfQ0KY29lZi4yX21hdHJpeCA8LSBtZ2V0KChscyhwYXQgPSAnY29lZl8nKSkpICU+JSAgYmluZF9yb3dzKCkNCg0KY29lZi4yX21hdHJpeA0KDQoNCmBgYA0KDQojIyBHcmFwaHMgd2l0aCBBbm9tYWx5IFNjb3Jlcw0KDQpgYGB7cn0NCmdyYXBoX2xpc3QuZmkgPC0gbGFwcGx5KDE6bGVuZ3RoKGJlc3RfZml0X25vbl9zZWFyY2hfZmkpLCBncmFwaGluZ19mdW5jdGlvbjRfd19hbm9tLCBkZjEgPSBiZXN0X2ZpdF9ub25fc2VhcmNoX2ZpLCBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maSkNCg0KIyMjIEFkZCBHRyBUZXh0IFJlcGVsDQpnZ3Bsb3RseShncmFwaF9saXN0LmZpW1szXV0pDQoNCmBgYA0KDQojIENyZWF0ZSBhbGwgUmVzcG9uc2UgQ3VydmVzIC0gUmlkZ2UvTGFzc28NCg0KYGBge3IsIHdhcm5pbmcgPSBGQUxTRX0NCg0Kc3RhcnRfdGltZSA8LSBTeXMudGltZSgpDQoNCmZpdHMubm9uLnNlYXJjaC5SSURHRV9MQVNTTyA8LSBsYXBwbHkoDQogIDE6bGVuZ3RoKGRmX25hbWVzKSwNCiAgZnVuY3Rpb24oaSkgew0KICAgIG1vZGVsX3dyYXBwZXJfZnVuY3Rpb24oZGYgPSBkZl9uYW1lc1tpXVtbMV1dLHBvbHlfaW5kID0gMCkNCiAgfQ0KKQ0KDQplbmRfdGltZSA8LSBTeXMudGltZSgpDQoNCmNvbWJpbmVkX3JpZGdlX3RpbWUgPC0gc3RhcnRfdGltZSAtIGVuZF90aW1lDQoNCmJlc3QuaW5kLm5vbi5zZWFyY2guUklER0VfTEFTU08gPC0gbGFwcGx5KA0KICAxOmxlbmd0aChkZl9uYW1lcyksDQogIGZ1bmN0aW9uKGkpIHsgICANCiAgbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzW2ldW1sxXV0pLCBiZXN0X2luZF9mdW5jdGlvbixkZiA9IGZpdHMubm9uLnNlYXJjaC5SSURHRV9MQVNTT1tpXVtbMV1dLA0KICAgICAgICAgZGYyID0gZGZfbmFtZXNbaV1bWzFdXSkNCiAgfQ0KKQ0KDQpjb2VmLm5vbi5zZWFyY2guUklER0VfTEFTU08gPC0gbGFwcGx5KA0KICAxOmxlbmd0aChkZl9uYW1lcyksDQogIGZ1bmN0aW9uIChpKXsNCiAgYmVzdC5pbmQubm9uLnNlYXJjaC5SSURHRV9MQVNTT1tpXVtbMV1dICU+JSBiaW5kX3Jvd3MNCiAgfQ0KKSAlPiUNCiAgYmluZF9yb3dzKCkgJT4lIA0KICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KIyAgbXV0YXRlKA0KIyAgICBjb3N0X3AyID0gMCwNCiMgICAgbGFtYmRhID0gMCwNCiMgICAgYWxwaGEgPSAwLA0KIyAgICBwb3dlcnMyID0gMA0KIyAgKSAlPiUgDQogIHNlbGVjdChvbmVfb2YoY29sbmFtZXMoY29lZi4yX21hdHJpeCkpKQ0KDQoNCmJlc3QuZml0Lm5vbi5zZWFyY2guUklER0VfTEFTU08gPC0gbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzKSwNCiAgICAgIGZ1bmN0aW9uKGopIHsNCmxhcHBseSgxOmxlbmd0aChiZXN0LmluZC5ub24uc2VhcmNoLlJJREdFX0xBU1NPW1tqXV0pLA0KICAgICAgZnVuY3Rpb24oaSl7DQogICAgICAgIGJlc3QuaW5kLm5vbi5zZWFyY2guUklER0VfTEFTU09bal1bWzFdXVtpXSAlPiUgDQogICAgICAgIHNldF9uYW1lcyhubSA9IGJlc3QuaW5kLm5vbi5zZWFyY2guUklER0VfTEFTU09bal1bWzFdXVtbaV1dWyJtb2RlbCJdKQ0KICAgICAgfSANCikNCiAgICAgIH0NCiAgICAgICApDQogIA0KDQoNCmBgYA0KDQoNCiMgQ3JlYXRlIGFsbCBSZXNwb25zZSBDdXJ2ZXMgLSBSTE0NCg0KYGBge3IsIHdhcm5pbmcgPSBGQUxTRX0NCg0KDQpzdGFydF90aW1lIDwtIFN5cy50aW1lKCkNCg0KZml0cy5ub24uc2VhcmNoLlJMTSA8LSBsYXBwbHkoDQogIDE6bGVuZ3RoKGRmX25hbWVzKSwNCiAgZnVuY3Rpb24oaSkgew0KICAgIG1vZGVsX3dyYXBwZXJfZnVuY3Rpb24yKGRmID0gZGZfbmFtZXNbaV1bWzFdXSkNCiAgfQ0KKQ0KDQplbmRfdGltZSA8LSBTeXMudGltZSgpDQoNCmNvbWJpbmVkX3JsbV90aW1lIDwtIHN0YXJ0X3RpbWUgLSBlbmRfdGltZQ0KDQpiZXN0LmluZC5ub24uc2VhcmNoLlJMTSA8LSBsYXBwbHkoDQogIDE6bGVuZ3RoKGRmX25hbWVzKSwNCiAgZnVuY3Rpb24oaSkgeyAgIA0KICBsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXNbaV1bWzFdXSksIGJlc3RfaW5kX2Z1bmN0aW9uLGRmID0gZml0cy5ub24uc2VhcmNoLlJMTVtpXVtbMV1dLA0KICAgICAgICAgZGYyID0gZGZfbmFtZXNbaV1bWzFdXSkNCiAgfQ0KKQ0KDQpjb2VmLm5vbi5zZWFyY2guUkxNIDwtIGxhcHBseSgNCiAgMTpsZW5ndGgoZGZfbmFtZXMpLA0KICBmdW5jdGlvbiAoaSl7DQogIGJlc3QuaW5kLm5vbi5zZWFyY2guUkxNW2ldW1sxXV0gJT4lIGJpbmRfcm93cw0KICB9DQopICU+JQ0KICBiaW5kX3Jvd3MoKSAlPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogIG11dGF0ZSgNCiAgICBjb3N0X3AyID0gMCwNCiAgICBsYW1iZGEgPSAwLA0KICAgIGFscGhhID0gMCwNCiAgICBwb3dlcnMyID0gMA0KICApICU+JSANCiAgc2VsZWN0KG9uZV9vZihjb2xuYW1lcyhjb2VmLjJfbWF0cml4KSkpDQoNCg0KYmVzdC5maXQubm9uLnNlYXJjaC5STE0gPC0gbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzKSwNCiAgICAgIGZ1bmN0aW9uKGopIHsNCmxhcHBseSgxOmxlbmd0aChiZXN0LmluZC5ub24uc2VhcmNoLlJMTVtbal1dKSwNCiAgICAgIGZ1bmN0aW9uKGkpew0KICAgICAgICBiZXN0LmluZC5ub24uc2VhcmNoLlJMTVtqXVtbMV1dW2ldICU+JSANCiAgICAgICAgc2V0X25hbWVzKG5tID0gYmVzdC5pbmQubm9uLnNlYXJjaC5STE1bal1bWzFdXVtbaV1dWyJtb2RlbCJdKQ0KICAgICAgfSANCikNCiAgICAgIH0NCiAgICAgICApDQoNCg0KICANCmBgYA0KDQoNCmBgYHtyfQ0KDQotY29tYmluZWRfcmlkZ2VfdGltZStjb21iaW5lZF9ybG1fdGltZQ0KDQpgYGANCg0KDQpgYGB7ciwgd2FybmluZyA9IEZBTFNFfQ0KDQpncmFwaC5saXN0LnJsbSA8LSBsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXMpLA0KICAgICAgZnVuY3Rpb24oaSl7DQogICAgICBsYXBwbHkoMTpsZW5ndGgoYmVzdC5maXQubm9uLnNlYXJjaC5STE1baV1bWzFdXSksIGdyYXBoaW5nX2Z1bmN0aW9uX3JsbSwgZGYxPSBiZXN0LmZpdC5ub24uc2VhcmNoLlJMTVtpXSxkZjIgPSBkZl9uYW1lc1tpXSkNCiAgICAgIH0gDQopDQoNCg0KZ3JhcGgubGlzdC5SSURHRV9MQVNTTyA8LSBsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXMpLA0KICAgICAgZnVuY3Rpb24oaSl7DQogICAgICBsYXBwbHkoMTpsZW5ndGgoYmVzdC5maXQubm9uLnNlYXJjaC5SSURHRV9MQVNTT1tpXVtbMV1dKSwgZ3JhcGhpbmdfZnVuY3Rpb25fZWxhc3RpY25ldCwgZGYxPSBiZXN0LmZpdC5ub24uc2VhcmNoLlJJREdFX0xBU1NPW2ldLGRmMiA9IGRmX25hbWVzW2ldKQ0KICAgICAgfSANCikNCg0KDQoNCg0KYGBgDQoNCg0KIyMjIEV4cG9ydCBhbGwgUGxvdHMNCg0KYGBge3J9DQoNCmZvbGRlcl9uYW1lMSA8LSBwYXN0ZTAoIk91dHB1dC8iLCAib3V0cHV0ZmlsZXNfIiwgU3lzLkRhdGUoKSwgIl8iLCAiUkxNIiwgIi8iKQ0KZGlyLmNyZWF0ZShmb2xkZXJfbmFtZTEpICMgaXQgd2lsbCB0aHJvdyBhIHdhcm5pbmcgaWYgZm9sZGVyIGV4aXN0cw0KDQpsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXMpLA0KICAgICAgZnVuY3Rpb24oaikgew0KbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzW1tqXV0pLGV4cG9ydF9ycGxvdHNfZnVuY3Rpb24yLHN0YXJ0aW5nX25hbWUgPSAiTm9uX1NlYXJjaF8iLGZvbGRlcl9uYW1lID0gZm9sZGVyX25hbWUxLGRmX2xpc3QgPSBkZl9uYW1lc1tbal1dLGdyYXBoaW5nX2xpc3QgPSBncmFwaC5saXN0LnJsbVtqXVtbMV1dKQ0KICAgICAgfQ0KICAgICAgICkNCg0KZm9sZGVyX25hbWUyIDwtIHBhc3RlMCgiT3V0cHV0LyIsICJvdXRwdXRmaWxlc18iLCBTeXMuRGF0ZSgpLCAiXyIsICJFbGFzdGljTmV0IiwgIi8iKQ0KZGlyLmNyZWF0ZShmb2xkZXJfbmFtZTIpICMgaXQgd2lsbCB0aHJvdyBhIHdhcm5pbmcgaWYgZm9sZGVyIGV4aXN0cw0KDQoNCmxhcHBseSgxOmxlbmd0aChkZl9uYW1lcyksDQogICAgICBmdW5jdGlvbihqKSB7DQpsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXNbW2pdXSksZXhwb3J0X3JwbG90c19mdW5jdGlvbjIsc3RhcnRpbmdfbmFtZSA9ICJOb25fU2VhcmNoXyIsZm9sZGVyX25hbWUgPSBmb2xkZXJfbmFtZTIsZGZfbGlzdCA9IGRmX25hbWVzW1tqXV0sZ3JhcGhpbmdfbGlzdCA9IGdyYXBoLmxpc3QuUklER0VfTEFTU09bal1bWzFdXSkNCiAgICAgIH0NCiAgICAgICApDQoNCmBgYA0KDQojIyMgU2hvdyBHcmFwaHMNCg0KYGBge3J9DQpsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXMpLA0KZnVuY3Rpb24oail7DQogIHN1YnBsb3QoZ3JhcGgubGlzdC5ybG1bal1bWzFdXSwgbnJvd3MgPSBsZW5ndGgoZ3JhcGgubGlzdC5ybG1bal1bWzFdXSkpDQp9DQopDQoNCg0KbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzKSwNCmZ1bmN0aW9uKGkpew0KI3AxID0gZ3JhcGhfbmFtZXNbaV1bWzFdXQ0KZG8uY2FsbChncmlkLmFycmFuZ2UsZ3JhcGgubGlzdC5ybG1baV1bWzFdXSkNCiNyZXR1cm4oZ3JpZC5hcnJhbmdlKGdyb2JzID0gcDEpKQ0KfQ0KKQ0KDQoNCg0KYGBgDQoNCmBgYHtyfQ0KbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzKSwNCmZ1bmN0aW9uKGopew0KICBzdWJwbG90KGdyYXBoLmxpc3QuUklER0VfTEFTU09bal1bWzFdXSwgbnJvd3MgPSBsZW5ndGgoZ3JhcGgubGlzdC5SSURHRV9MQVNTT1tqXVtbMV1dKSkNCn0NCikNCg0KDQpsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXMpLA0KZnVuY3Rpb24oaSl7DQojcDEgPSBncmFwaF9uYW1lc1tpXVtbMV1dDQpkby5jYWxsKGdyaWQuYXJyYW5nZSxncmFwaC5saXN0LlJJREdFX0xBU1NPW2ldW1sxXV0pDQojcmV0dXJuKGdyaWQuYXJyYW5nZShncm9icyA9IHAxKSkNCn0NCikNCg0KYGBgDQoNCg0KIyBUZXN0aW5nIE1ldGFmb3IgUGFja2FnZQ0KDQpgYGB7cn0NCg0KcF9sb2FkKGxtZTQpDQpwX2xvYWQobWV0YWZvcmVzdCkNCg0KYGBgDQoNCiMjIFRlc3Rpbmcgb24gRFNNIERhdGENCg0KIyMjIExvYWQgaW4gRGF0YQ0KYGBge3J9DQoNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX3ByZSA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZSAlPiUNCiAgZmlsdGVyKHBhID09ICJEU00iKSAlPiUNCiAgZmlsdGVyKHJlZ2lvbl92MiAhPSAiQVBBQyIpICU+JQ0KICAjIGZpbHRlcihhYnNvbHV0ZV9saWZ0IDwgMTAwMCkgIyAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0gJzYyOTc0MjAnKSAjJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPScxNDkxNjE3MTEnKSAlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9ICcxNDg2MTMwMDInKSAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzI4NDYyNScpICU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzMyOTEzMScpDQogIG11dGF0ZSgNCiAgICBpZDIgPSByb3dfbnVtYmVyKCkNCiAgKQ0KDQpkZl90ZXN0IDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9wcmUgJT4lDQogICMgc2VsZWN0KC1zdHVkeV9pZCwgLWlkMiwgLXJlZ2lvbiwgLXNjYWxpbmdfZmFjdG9yLCAtcXVhcnRlciwgLXBhLCAtc3R1ZHlfbmFtZSkNCiAgc2VsZWN0KA0KICAgIHJlZ2lvbl92MiwgY291bnRyeSwgY2hhbm5lbCwgdGFjdGljLA0KICAgICMgdHJlYXRtZW50X3VzZXJfY291bnQ6Y29udHJvbCwNCiAgICBjb3N0X3NwZW50X29uX2V4cG9zZWRfZ3JvdXA6YWJzb2x1dGVfbGlmdA0KICApDQoNCmlzb19kc20gPC0gaXNvbGF0aW9uRm9yZXN0JG5ldyhzYW1wbGVfc2l6ZSA9IG5yb3coZGZfdGVzdCksIG51bV90cmVlcyA9IDEwMDAwLCBzZWVkID0gMTE1MikNCg0KaXNvX2RzbSRmaXQoZGZfdGVzdCkNCg0Kc2NvcmVzX3RyYWluIDwtIGRmX3Rlc3QgJT4lDQogIGlzb19kc20kcHJlZGljdCgpICU+JQ0KICBhcnJhbmdlKGRlc2MoYW5vbWFseV9zY29yZSkpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9NZXRhNF9WMSA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9kc21fcHJlICU+JQ0KICBsZWZ0X2pvaW4oc2NvcmVzX3RyYWluLCBieSA9IGMoImlkMiIgPSAiaWQiKSkgJT4lDQogZmlsdGVyKGF2ZXJhZ2VfZGVwdGggPiA1LjEpDQoNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX01ldGE0IDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9NZXRhNF9WMSAlPiUNCiAgbmFtZWRfZ3JvdXBfc3BsaXQocmVnaW9uX3YyKQ0KDQpgYGANCg0KIyMjIFN0YW5kYXJkaXplIERhdGENCg0KYGBge3J9DQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9kc21fTWV0YTRfVjEgJT4lIA0KICBtdXRhdGUoDQogICAgDQogICkNCmBgYA0KDQoNCiMjIyBSdW4gYSBGaXhlZC1FZmZlY3RzIE1vZGVsDQpbRG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9janZhbmxpc3NhLmdpdGh1Yi5pby9Eb2luZy1NZXRhLUFuYWx5c2lzLWluLVIvZml4ZWRlZi5odG1sKQ0KYGBge3IsIGZpZy5oZWlnaHQ9IDE1fQ0KDQoNCiNkZl9zbWQgDQoNCg0KaSA9IDENCg0KeWlfRFNNID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX01ldGE0W1tpXV1bJ2Fic29sdXRlX2xpZnQnXSAlPiUgdW5saXN0KCkNCnZpX0RTTSA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9NZXRhNFtbaV1dWydTaWduaWZpY2FudF9TcGVuZCddXjEgJT4lIHVubGlzdCgpDQpzcGxpdDIgPSBmYWN0b3IoRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX01ldGE0W1tpXV1bJ2NoYW5uZWwnXSAlPiUgdW5saXN0KCksbGFiZWxzID0gdW5pcXVlKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9NZXRhNFtbaV1dWydjaGFubmVsJ10pICU+JSB1bmxpc3QoKSkNCg0KDQptX3JlZyA8LSBybWEoeWkgPSB5aV9EU00sICAgICAjIFRoZSBkLWNvbHVtbiBvZiB0aGUgZGYsIHdoaWNoIGNvbnRhaW5zIENvaGVuJ3MgZA0KICAgICAgICAgdmkgPSB2aV9EU00gICAjIFRoZSB2aS1jb2x1bW4gb2YgdGhlIGRmLCB3aGljaCBjb250YWlucyB0aGUgdmFyaWFuY2VzDQogICAgICAgICAsbW9kcyA9IH5zcGxpdDItMSAjdG8gcmVtb3ZlIGludGVyY2VwdCBiZXR3ZWVuIHNsb3Blcw0KICAgICAgICAgKSAgDQogICAgICAgDQoNCm1vZDFfdGVzdA0KDQojcm0oRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX01ldGE0X1YxKSMsbW9kMV90ZXN0LCBpKQ0KDQpwcmVkaWN0KG1vZDFfdGVzdCkNCg0KDQpmb3Jlc3QobW9kMV90ZXN0LCBzbGFiID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX01ldGE0W1tpXV1bJ3N0dWR5X25hbWUnXSAlPiUgdW5saXN0KCksIGFkZGNyZWQgPSBUUlVFKQ0KYGBgDQojIyMgQWRkaXRpb25hbCBUZXN0DQoNCmBgYHtyfQ0KDQojIFNwZWNpZnkgYmFzaWMgcGxvdCwgbWFwcGluZyBzZXggdG8gdGhlIHgtYXhpcywgZWZmZWN0IHNpemUgJ2QnIHRvIHRoZSB5LWF4aXMsDQojIGFuZCAnd2VpZ2h0cycgdG8gdGhlIHdlaWdodCBwYXJhbWV0ZXIuDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9NZXRhNFtbaV1dICU+JSANCiAgZ2dwbG90KCkrDQogIGFlcygNCiAgICB4ID0gY29zdF9zcGVudF9vbl9leHBvc2VkX2dyb3VwLA0KICAgIHkgPSBhYnNvbHV0ZV9saWZ0LA0KICAgIHNpemUgPSAxL3NxcnQoY29zdF9zcGVudF9vbl9leHBvc2VkX2dyb3VwKQ0KICApICsNCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsgIyBBZGQgc2NhdHRlcg0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSBtX3JlZyRiWzFdLCBzbG9wZSA9IG1fcmVnJGJbM10pICsgIyBBZGQgcmVncmVzc2lvbiBsaW5lDQogIHRoZW1lX2J3KCkgKyAjIEFwcGx5IGJsYWNrIGFuZCB3aGl0ZSB0aGVtZQ0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICMgUmVtb3ZlIGxlZ2VuZA0KDQpgYGANCg0KYGBge3J9DQoNCmBgYA0KDQo=